This is an R Markdown Notebook for analysis using data on the DC Bus System (WMATA Metrobus). The data were obtained here:

https://planitmetro.com/2016/11/16/data-download-metrobus-vehicle-location-data/

Control + Alt + Shift + m = rename in scope

Load the packages to be used.

package ‘tidyr’ was built under R version 3.2.5package ‘plyr’ was built under R version 3.2.5package ‘stringr’ was built under R version 3.2.5package ‘geosphere’ was built under R version 3.2.5

Get the Bus data.

First let’s check the working directory.

getwd()
[1] "/Users/mdturse/Desktop/Analytics/DCMetroBus"

Then, actually get the data.

The working directory was changed to /Users/mdturse/Desktop/Analytics/DCMetroBus/Bus AVL Oct 2016 inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the the working directory for notebook chunks.Oct03Raw
'data.frame':   620274 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 11 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : Factor w/ 10552 levels "","1000001","1000003",..: 9682 9682 9683 9641 9640 8136 9668 9668 9796 9795 ...
 $ Stop_Desc        : Factor w/ 7740 levels "10TH ST + MICHIGAN AVE",..: 1346 1346 7417 7418 1346 2940 2939 2939 6926 6929 ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : Factor w/ 75354 levels "10-3-16 1:00:00 AM",..: 47380 47506 47740 47814 47864 48244 48302 48540 49086 49190 ...
 $ Departure_Time   : Factor w/ 75396 levels "10-3-16 1:00:00 AM",..: 47406 47554 47766 47840 47890 48270 48536 48566 49112 49216 ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
Oct04Raw
'data.frame':   623427 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 225 225 225 225 225 225 225 225 225 225 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 6 6 6 6 6 6 6 ...
 $ Route_Direction  : Factor w/ 9 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 8 1 1 1 1 3 2 5 ...
 $ Stop_ID          : Factor w/ 10555 levels "","1000001","1000003",..: 9671 9671 8138 8138 8138 8138 8138 9798 9799 9638 ...
 $ Stop_Desc        : Factor w/ 7717 levels "10TH ST + MICHIGAN AVE",..: 2939 2939 2940 2940 2940 2940 2940 6906 6903 4205 ...
 $ Event_Type       : int  3 4 3 3 3 5 5 4 5 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 3 1 1 1 2 2 3 2 3 ...
 $ Event_Time       : Factor w/ 77713 levels "10-4-16 1:00:00 AM",..: 49126 49240 50858 50908 50976 51116 51172 51714 51842 51940 ...
 $ Departure_Time   : Factor w/ 77739 levels "10-4-16 1:00:00 AM",..: 49209 49251 50869 50957 50987 51165 51185 51725 51933 51951 ...
 $ Dwell_Time       : int  79 0 59 19 59 19 1 0 40 0 ...
 $ Delta_Time       : int  35 36 36 246 244 255 264 159 129 139 ...
 $ Odometer_Distance: int  56958 60750 69747 69971 69747 71136 71177 76520 77425 78353 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  58 89 82 76 79 301 274 104 310 2 ...
Oct05Raw
'data.frame':   630900 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Route_Direction  : Factor w/ 11 levels "ANTICLKW","CLOCKWIS",..: 5 5 5 5 5 5 5 5 5 5 ...
 $ Stop_Sequence    : int  1 1 3 4 5 4 3 3 7 7 ...
 $ Stop_ID          : Factor w/ 10543 levels "","1000001","1000003",..: 9659 9659 9632 9633 9624 9633 9632 9632 9673 9673 ...
 $ Stop_Desc        : Factor w/ 7725 levels "10TH ST + MICHIGAN AVE",..: 2946 2946 7403 7401 7401 7401 7403 7403 1346 1346 ...
 $ Event_Type       : int  3 5 4 4 3 4 3 3 5 5 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 2 3 3 1 3 1 1 2 2 ...
 $ Event_Time       : Factor w/ 77725 levels "10-5-16 1:00:00 AM",..: 49279 49371 49899 49953 49993 50135 50221 50493 50783 50987 ...
 $ Departure_Time   : Factor w/ 77716 levels "10-5-16 1:00:00 AM",..: 49257 49353 49877 49931 49997 50113 50421 50489 50767 50999 ...
 $ Dwell_Time       : int  189 2 0 0 13 0 111 9 3 17 ...
 $ Delta_Time       : int  4 78 -114 -3 19 93 297 191 382 499 ...
 $ Odometer_Distance: int  37932 38703 44242 44327 44645 45927 46733 47077 50461 51916 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  316 104 276 246 229 246 345 207 109 305 ...
Oct06Raw
'data.frame':   621948 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 265 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Route_Direction  : Factor w/ 9 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 7 6 5 4 3 7 7 7 ...
 $ Stop_ID          : Factor w/ 10562 levels "","1000001","1000003",..: 9678 9678 9692 9693 9643 9652 9651 9692 9692 9692 ...
 $ Stop_Desc        : Factor w/ 7723 levels "10TH ST + MICHIGAN AVE",..: 2937 2937 1342 7400 7399 7399 7401 1342 1342 1342 ...
 $ Event_Type       : int  3 5 4 5 3 4 3 4 5 5 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 2 3 2 1 3 1 3 2 2 ...
 $ Event_Time       : Factor w/ 77758 levels "10-6-16 1:00:00 AM",..: 49294 49384 49982 49998 50058 50186 50270 50518 51002 51064 ...
 $ Departure_Time   : Factor w/ 77792 levels "10-6-16 1:00:00 AM",..: 49305 49399 49993 50023 50091 50197 50487 50529 51065 51079 ...
 $ Dwell_Time       : int  148 2 0 7 11 0 103 0 26 2 ...
 $ Delta_Time       : int  -6 64 -87 -93 31 104 303 175 497 504 ...
 $ Odometer_Distance: int  37950 38726 44130 44197 44592 45935 46739 51826 51826 51838 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  284 71 199 164 223 246 343 199 306 320 ...
Oct07Raw
'data.frame':   622894 obs. of  17 variables:
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : Factor w/ 266 levels "10A","10B","10E",..: 224 224 224 224 224 224 224 224 224 224 ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 6 6 6 6 6 6 7 7 ...
 $ Route_Direction  : Factor w/ 7 levels "ANTICLKW","CLOCKWIS",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ Stop_Sequence    : int  1 1 2 3 3 5 6 7 1 2 ...
 $ Stop_ID          : Factor w/ 10556 levels "","1000001","1000003",..: 9672 9672 9800 9799 9799 9639 9640 9641 9641 9642 ...
 $ Stop_Desc        : Factor w/ 7699 levels "10TH ST + MICHIGAN AVE",..: 2930 2930 6886 6889 6889 4196 4199 6887 6887 4198 ...
 $ Event_Type       : int  3 4 3 4 5 4 4 3 3 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 1 3 1 3 2 3 3 1 1 3 ...
 $ Event_Time       : Factor w/ 77562 levels "10-7-16 1:00:00 AM",..: 49134 49136 51718 51756 51888 51934 52018 52044 52130 52288 ...
 $ Departure_Time   : Factor w/ 77649 levels "10-7-16 1:00:00 AM",..: 49193 49195 51779 51815 51953 51993 52077 52103 52189 52347 ...
 $ Dwell_Time       : int  153 0 1 0 3 0 0 120 120 0 ...
 $ Delta_Time       : int  57 56 165 270 197 201 181 189 235 288 ...
 $ Odometer_Distance: int  37846 42154 56018 56611 57411 58341 59084 59787 59787 60252 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  98 89 201 104 26 2 1 247 247 182 ...

Put the daily data together.

AllDays <- bind_rows(list(Oct03Raw, Oct04Raw, Oct05Raw, Oct06Raw, Oct07Raw),
                     .id = c("group")
                    )
Unequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to characterUnequal factor levels: coercing to character
# dim(AllDays)
str(AllDays)
'data.frame':   3119443 obs. of  18 variables:
 $ group            : chr  "1" "1" "1" "1" ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : chr  "LOOP" "LOOP" "LOOP" "LOOP" ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : chr  "10-3-16 6:06:47 AM" "10-3-16 6:07:50 AM" "10-3-16 6:09:47 AM" "10-3-16 6:10:24 AM" ...
 $ Departure_Time   : chr  "10-3-16 6:06:47 AM" "10-3-16 6:08:01 AM" "10-3-16 6:09:47 AM" "10-3-16 6:10:24 AM" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...

Deleting old data frames.

for (i in 3:7){
  rm(list = ls(pattern = paste0("Oct0", i, "Raw")
              )
    )
  
  message("Deleting Oct0", i, "Raw")
  }
Deleting Oct03Raw
Deleting Oct04Raw
Deleting Oct05Raw
Deleting Oct06Raw
Deleting Oct07Raw

Updating variable types.

Then, sorting the data and adding a RowNumber (to be used for identifying rows later in the analyses.)

rm(i)
AllDays$group <- factor(AllDays$group)
AllDays$Route_Direction <- factor(AllDays$Route_Direction)
AllDays$Event_Time <- as.POSIXct(AllDays$Event_Time, format = "%m-%d-%y %I:%M:%S %p")
AllDays$Departure_Time <- as.POSIXct(AllDays$Departure_Time, format = "%m-%d-%y %I:%M:%S %p")
str(AllDays)
'data.frame':   3119443 obs. of  18 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
AllDays_Sorted <- arrange(AllDays,
                          Bus_ID,
                          Event_Time
                         ) %>% 
  mutate(RowNum_OG = row_number() # this is useful in identify the row later on
        )
rm(AllDays)
str(AllDays_Sorted)
'data.frame':   3119443 obs. of  19 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
# View(head(AllDays_Sorted, 100))

Inspecting the values of Stop_ID, and finding that it can take the values “” (blank) and “NULL”.

View(group_by(AllDays_Sorted,
              Stop_ID
             ) %>% 
       summarise(
         Cnt = n()
         ) %>% 
       arrange(Stop_ID)
    )
View(filter(AllDays_Sorted,
            is.na(Stop_ID) |
              Stop_ID == "" |
              Stop_ID == "NULL"
           ) %>% 
       arrange(Stop_Desc)
    )

Creating a table of distinct Stop_Desc values when Stop_ID is “” (blank) or “NULL”.

StopID_New <- filter(AllDays_Sorted,
                     is.na(Stop_ID) |
                       Stop_ID == "" |
                       Stop_ID == "NULL"
                    ) %>% 
  select(Stop_ID, Stop_Desc) %>% 
  distinct() %>% 
  arrange(Stop_ID, Stop_Desc) %>% 
  mutate(StopID_New = 1:nrow(.)
        )
View(StopID_New)

Creating a full updated table by filling in StopID_New for when Stop_ID is “” (blank) or NULL.

AllDays_StopIDNew <- left_join(AllDays_Sorted,
                               select(StopID_New,
                                      Stop_Desc,
                                      StopID_New
                                     ),
                               by = c("Stop_Desc" = "Stop_Desc")
                              ) %>% 
  mutate(StopID_Clean = ifelse(is.na(StopID_New),
                               Stop_ID,
                               StopID_New
                              ),
         StopID_Indicator = factor(ifelse(is.na(StopID_New),
                                          "ID_OK",
                                          "ID_Bad"
                                         )
                                  )
        )
rm(StopID_New)
rm(AllDays_Sorted)
str(AllDays_StopIDNew)
'data.frame':   3119443 obs. of  22 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 1 1 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 7 6 3 2 8 1 1 2 3 ...
 $ Stop_ID          : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ Event_Type       : int  4 5 4 4 4 3 3 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 2 3 3 3 1 1 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:07:50" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:08:01" ...
 $ Dwell_Time       : int  0 11 0 0 0 0 104 0 0 0 ...
 $ Delta_Time       : int  -177 -27 24 165 25 73 719 0 74 76 ...
 $ Odometer_Distance: int  43543 43543 45139 46418 50115 51074 51303 53836 55633 56163 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 253 97 276 15 119 100 89 274 104 ...
 $ RowNum_OG        : int  1 2 3 4 5 6 7 8 9 10 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004572" "5004573" "5002210" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
# View(tail(AllDays_StopIDNew, 500))
# View(filter(AllDays_StopIDNew,
#             Stop_Desc == "METROWAY ANNNOUCEMNT CORR"
#            )
#     )

Lat Long stats for pulling in Zip codes later.

LL_Stats <- group_by(AllDays_StopIDNew,
                     StopID_Clean
                    ) %>% 
  summarise(Lat_Mean = mean(Latitude, na.rm = TRUE),
            Lat_Med = median(Latitude, na.rm = TRUE),
            Lng_Mean = mean(Longitude, na.rm = TRUE),
            Lng_Med = median(Longitude, na.rm = TRUE)
           ) %>% 
  mutate(Lat_MeaLessMed = Lat_Mean - Lat_Med,
         Lng_MeaLessMed = Lng_Mean - Lng_Med,
         RowNum = row_number()
        )
str(LL_Stats)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   10588 obs. of  8 variables:
 $ StopID_Clean  : chr  "1" "10" "1000001" "1000003" ...
 $ Lat_Mean      : num  38.9 39 38.8 38.8 38.8 ...
 $ Lat_Med       : num  38.9 39 38.8 38.8 38.8 ...
 $ Lng_Mean      : num  -77.1 -77.4 -77 -77 -77 ...
 $ Lng_Med       : num  -77.1 -77.4 -77 -77 -77 ...
 $ Lat_MeaLessMed: num  8.37e-05 0.00 -5.40e-06 2.15e-05 9.27e-06 ...
 $ Lng_MeaLessMed: num  -8.47e-05 0.00 1.07e-05 1.62e-04 -4.82e-07 ...
 $ RowNum        : int  1 2 3 4 5 6 7 8 9 10 ...
summary(LL_Stats)
 StopID_Clean          Lat_Mean        Lat_Med         Lng_Mean     
 Length:10588       Min.   :38.09   Min.   :38.60   Min.   :-77.45  
 Class :character   1st Qu.:38.85   1st Qu.:38.85   1st Qu.:-77.10  
 Mode  :character   Median :38.90   Median :38.90   Median :-77.01  
                    Mean   :38.91   Mean   :38.91   Mean   :-77.03  
                    3rd Qu.:38.96   3rd Qu.:38.96   3rd Qu.:-76.95  
                    Max.   :39.19   Max.   :39.19   Max.   :-75.42  
    Lng_Med       Lat_MeaLessMed       Lng_MeaLessMed           RowNum     
 Min.   :-77.45   Min.   :-0.8069882   Min.   :-0.0102476   Min.   :    1  
 1st Qu.:-77.10   1st Qu.:-0.0000126   1st Qu.:-0.0000167   1st Qu.: 2648  
 Median :-77.01   Median : 0.0000003   Median :-0.0000003   Median : 5294  
 Mean   :-77.03   Mean   :-0.0001867   Mean   : 0.0003654   Mean   : 5294  
 3rd Qu.:-76.95   3rd Qu.: 0.0000141   3rd Qu.: 0.0000148   3rd Qu.: 7941  
 Max.   :-76.67   Max.   : 0.0093569   Max.   : 1.6050662   Max.   :10588  
View(head(arrange(LL_Stats,
                  Lat_MeaLessMed
                 ),
          500
         )
    )
View(head(arrange(LL_Stats,
                  desc(Lat_MeaLessMed)
                 ),
          500
         )
    )
View(head(arrange(LL_Stats,
                  Lng_MeaLessMed
                 ),
          500
         )
    )
View(head(arrange(LL_Stats,
                  desc(Lng_MeaLessMed)
                 ),
          500
         )
    )

Pulling in Zip Code data.

# pages <- list()
# pages2 <- list()
# pages3 <- list()
# pages4 <- list()
pages5 <- list()
# pages6 <- list()
# max_row_per_hr <- 1000
# need to group in bunches as http://api.geonames.org limits pulls to 2000 per hour
system.time(
#   for(j in 0:5){
#   for(k in ((max_row_per_hr*j) + 1):(max_row_per_hr*(j+1)
#                                     )
#      ){
#     
#   }
# }
for(# i in 1:nrow(LL_Stats)
    # i in 1:1950
    i in 1:1000 # 2051 #3900
    # i in 3901:5850
    # i in 5851:7800
    # i in 7801:9750
    # i in 9751:nrow(LL_Stats)
   ){
  lat <- filter(LL_Stats,
                RowNum == (i + 1950 + 1000 + 1000 + 1000)
               ) %>%
    select(Lat_Med)
  # lat <- LL_Stats_Test[i, Lat_Med]
  
  lng <- filter(LL_Stats,
                RowNum == (i + 1950 + 1000 + 1000 + 1000)
               ) %>%
    select(Lng_Med)
  # lng <- LL_Stats_Test[i, Lng_Med]
  
  # APIData <- fromJSON(paste0(url_1,
  # APIData2 <- fromJSON(paste0(url_1,
  # APIData3 <- fromJSON(paste0(url_1,
  # APIData4 <- fromJSON(paste0(url_1,
  APIData5 <- fromJSON(paste0(url_1,
  # APIData6 <- fromJSON(paste0(url_1,
                             lat,
                             url_2,
                             lng,
                             url_3,
                             username
                            ),
                      flatten = TRUE
                     )
  
  message("Retrieving Zip Code ", (i + 1950 + 1000 + 1000 + 1000)
         )
  
  # pages[[i]] <- APIData$postalCodes
  # pages2[[i]] <- APIData2$postalCodes
  # pages3[[i]] <- APIData3$postalCodes
  # pages4[[i]] <- APIData4$postalCodes
  pages5[[i]] <- APIData5$postalCodes
  # pages6[[i]] <- APIData6$postalCodes
  
  # Sys.sleep(3900)
}
)
Retrieving Zip Code 4951
Retrieving Zip Code 4952
Retrieving Zip Code 4953
Retrieving Zip Code 4954
Retrieving Zip Code 4955
Retrieving Zip Code 4956
Retrieving Zip Code 4957
Retrieving Zip Code 4958
Retrieving Zip Code 4959
Retrieving Zip Code 4960
Retrieving Zip Code 4961
Retrieving Zip Code 4962
Retrieving Zip Code 4963
Retrieving Zip Code 4964
Retrieving Zip Code 4965
Retrieving Zip Code 4966
Retrieving Zip Code 4967
Retrieving Zip Code 4968
Retrieving Zip Code 4969
Retrieving Zip Code 4970
Retrieving Zip Code 4971
Retrieving Zip Code 4972
Retrieving Zip Code 4973
Retrieving Zip Code 4974
Retrieving Zip Code 4975
Retrieving Zip Code 4976
Retrieving Zip Code 4977
Retrieving Zip Code 4978
Retrieving Zip Code 4979
Retrieving Zip Code 4980
Retrieving Zip Code 4981
Retrieving Zip Code 4982
Retrieving Zip Code 4983
Retrieving Zip Code 4984
Retrieving Zip Code 4985
Retrieving Zip Code 4986
Retrieving Zip Code 4987
Retrieving Zip Code 4988
Retrieving Zip Code 4989
Retrieving Zip Code 4990
Retrieving Zip Code 4991
Retrieving Zip Code 4992
Retrieving Zip Code 4993
Retrieving Zip Code 4994
Retrieving Zip Code 4995
Retrieving Zip Code 4996
Retrieving Zip Code 4997
Retrieving Zip Code 4998
Retrieving Zip Code 4999
Retrieving Zip Code 5000
Retrieving Zip Code 5001
Retrieving Zip Code 5002
Retrieving Zip Code 5003
Retrieving Zip Code 5004
Retrieving Zip Code 5005
Retrieving Zip Code 5006
Retrieving Zip Code 5007
Retrieving Zip Code 5008
Retrieving Zip Code 5009
Retrieving Zip Code 5010
Retrieving Zip Code 5011
Retrieving Zip Code 5012
Retrieving Zip Code 5013
Retrieving Zip Code 5014
Retrieving Zip Code 5015
Retrieving Zip Code 5016
Retrieving Zip Code 5017
Retrieving Zip Code 5018
Retrieving Zip Code 5019
Retrieving Zip Code 5020
Retrieving Zip Code 5021
Retrieving Zip Code 5022
Retrieving Zip Code 5023
Retrieving Zip Code 5024
Retrieving Zip Code 5025
Retrieving Zip Code 5026
Retrieving Zip Code 5027
Retrieving Zip Code 5028
Retrieving Zip Code 5029
Retrieving Zip Code 5030
Retrieving Zip Code 5031
Retrieving Zip Code 5032
Retrieving Zip Code 5033
Retrieving Zip Code 5034
Retrieving Zip Code 5035
Retrieving Zip Code 5036
Retrieving Zip Code 5037
Retrieving Zip Code 5038
Retrieving Zip Code 5039
Retrieving Zip Code 5040
Retrieving Zip Code 5041
Retrieving Zip Code 5042
Retrieving Zip Code 5043
Retrieving Zip Code 5044
Retrieving Zip Code 5045
Retrieving Zip Code 5046
Retrieving Zip Code 5047
Retrieving Zip Code 5048
Retrieving Zip Code 5049
Retrieving Zip Code 5050
Retrieving Zip Code 5051
Retrieving Zip Code 5052
Retrieving Zip Code 5053
Retrieving Zip Code 5054
Retrieving Zip Code 5055
Retrieving Zip Code 5056
Retrieving Zip Code 5057
Retrieving Zip Code 5058
Retrieving Zip Code 5059
Retrieving Zip Code 5060
Retrieving Zip Code 5061
Retrieving Zip Code 5062
Retrieving Zip Code 5063
Retrieving Zip Code 5064
Retrieving Zip Code 5065
Retrieving Zip Code 5066
Retrieving Zip Code 5067
Retrieving Zip Code 5068
Retrieving Zip Code 5069
Retrieving Zip Code 5070
Retrieving Zip Code 5071
Retrieving Zip Code 5072
Retrieving Zip Code 5073
Retrieving Zip Code 5074
Retrieving Zip Code 5075
Retrieving Zip Code 5076
Retrieving Zip Code 5077
Retrieving Zip Code 5078
Retrieving Zip Code 5079
Retrieving Zip Code 5080
Retrieving Zip Code 5081
Retrieving Zip Code 5082
Retrieving Zip Code 5083
Retrieving Zip Code 5084
Retrieving Zip Code 5085
Retrieving Zip Code 5086
Retrieving Zip Code 5087
Retrieving Zip Code 5088
Retrieving Zip Code 5089
Retrieving Zip Code 5090
Retrieving Zip Code 5091
Retrieving Zip Code 5092
Retrieving Zip Code 5093
Retrieving Zip Code 5094
Retrieving Zip Code 5095
Retrieving Zip Code 5096
Retrieving Zip Code 5097
Retrieving Zip Code 5098
Retrieving Zip Code 5099
Retrieving Zip Code 5100
Retrieving Zip Code 5101
Retrieving Zip Code 5102
Retrieving Zip Code 5103
Retrieving Zip Code 5104
Retrieving Zip Code 5105
Retrieving Zip Code 5106
Retrieving Zip Code 5107
Retrieving Zip Code 5108
Retrieving Zip Code 5109
Retrieving Zip Code 5110
Retrieving Zip Code 5111
Retrieving Zip Code 5112
Retrieving Zip Code 5113
Retrieving Zip Code 5114
Retrieving Zip Code 5115
Retrieving Zip Code 5116
Retrieving Zip Code 5117
Retrieving Zip Code 5118
Retrieving Zip Code 5119
Retrieving Zip Code 5120
Retrieving Zip Code 5121
Retrieving Zip Code 5122
Retrieving Zip Code 5123
Retrieving Zip Code 5124
Retrieving Zip Code 5125
Retrieving Zip Code 5126
Retrieving Zip Code 5127
Retrieving Zip Code 5128
Retrieving Zip Code 5129
Retrieving Zip Code 5130
Retrieving Zip Code 5131
Retrieving Zip Code 5132
Retrieving Zip Code 5133
Retrieving Zip Code 5134
Retrieving Zip Code 5135
Retrieving Zip Code 5136
Retrieving Zip Code 5137
Retrieving Zip Code 5138
Retrieving Zip Code 5139
Retrieving Zip Code 5140
Retrieving Zip Code 5141
Retrieving Zip Code 5142
Retrieving Zip Code 5143
Retrieving Zip Code 5144
Retrieving Zip Code 5145
Retrieving Zip Code 5146
Retrieving Zip Code 5147
Retrieving Zip Code 5148
Retrieving Zip Code 5149
Retrieving Zip Code 5150
Retrieving Zip Code 5151
Retrieving Zip Code 5152
Retrieving Zip Code 5153
Retrieving Zip Code 5154
Retrieving Zip Code 5155
Retrieving Zip Code 5156
Retrieving Zip Code 5157
Retrieving Zip Code 5158
Retrieving Zip Code 5159
Retrieving Zip Code 5160
Retrieving Zip Code 5161
Retrieving Zip Code 5162
Retrieving Zip Code 5163
Retrieving Zip Code 5164
Retrieving Zip Code 5165
Retrieving Zip Code 5166
Retrieving Zip Code 5167
Retrieving Zip Code 5168
Retrieving Zip Code 5169
Retrieving Zip Code 5170
Retrieving Zip Code 5171
Retrieving Zip Code 5172
Retrieving Zip Code 5173
Retrieving Zip Code 5174
Retrieving Zip Code 5175
Retrieving Zip Code 5176
Retrieving Zip Code 5177
Retrieving Zip Code 5178
Retrieving Zip Code 5179
Retrieving Zip Code 5180
Retrieving Zip Code 5181
Retrieving Zip Code 5182
Retrieving Zip Code 5183
Retrieving Zip Code 5184
Retrieving Zip Code 5185
Retrieving Zip Code 5186
Retrieving Zip Code 5187
Retrieving Zip Code 5188
Retrieving Zip Code 5189
Retrieving Zip Code 5190
Retrieving Zip Code 5191
Retrieving Zip Code 5192
Retrieving Zip Code 5193
Retrieving Zip Code 5194
Retrieving Zip Code 5195
Retrieving Zip Code 5196
Retrieving Zip Code 5197
Retrieving Zip Code 5198
Retrieving Zip Code 5199
Retrieving Zip Code 5200
Retrieving Zip Code 5201
Retrieving Zip Code 5202
Retrieving Zip Code 5203
Retrieving Zip Code 5204
Retrieving Zip Code 5205
Retrieving Zip Code 5206
Retrieving Zip Code 5207
Retrieving Zip Code 5208
Retrieving Zip Code 5209
Retrieving Zip Code 5210
Retrieving Zip Code 5211
Retrieving Zip Code 5212
Retrieving Zip Code 5213
Retrieving Zip Code 5214
Retrieving Zip Code 5215
Retrieving Zip Code 5216
Retrieving Zip Code 5217
Retrieving Zip Code 5218
Retrieving Zip Code 5219
Retrieving Zip Code 5220
Retrieving Zip Code 5221
Retrieving Zip Code 5222
Retrieving Zip Code 5223
Retrieving Zip Code 5224
Retrieving Zip Code 5225
Retrieving Zip Code 5226
Retrieving Zip Code 5227
Retrieving Zip Code 5228
Retrieving Zip Code 5229
Retrieving Zip Code 5230
Retrieving Zip Code 5231
Retrieving Zip Code 5232
Retrieving Zip Code 5233
Retrieving Zip Code 5234
Retrieving Zip Code 5235
Retrieving Zip Code 5236
Retrieving Zip Code 5237
Retrieving Zip Code 5238
Retrieving Zip Code 5239
Retrieving Zip Code 5240
Retrieving Zip Code 5241
Retrieving Zip Code 5242
Retrieving Zip Code 5243
Retrieving Zip Code 5244
Retrieving Zip Code 5245
Retrieving Zip Code 5246
Retrieving Zip Code 5247
Retrieving Zip Code 5248
Retrieving Zip Code 5249
Retrieving Zip Code 5250
Retrieving Zip Code 5251
Retrieving Zip Code 5252
Retrieving Zip Code 5253
Retrieving Zip Code 5254
Retrieving Zip Code 5255
Retrieving Zip Code 5256
Retrieving Zip Code 5257
Retrieving Zip Code 5258
Retrieving Zip Code 5259
Retrieving Zip Code 5260
Retrieving Zip Code 5261
Retrieving Zip Code 5262
Retrieving Zip Code 5263
Retrieving Zip Code 5264
Retrieving Zip Code 5265
Retrieving Zip Code 5266
Retrieving Zip Code 5267
Retrieving Zip Code 5268
Retrieving Zip Code 5269
Retrieving Zip Code 5270
Retrieving Zip Code 5271
Retrieving Zip Code 5272
Retrieving Zip Code 5273
Retrieving Zip Code 5274
Retrieving Zip Code 5275
Retrieving Zip Code 5276
Retrieving Zip Code 5277
Retrieving Zip Code 5278
Retrieving Zip Code 5279
Retrieving Zip Code 5280
Retrieving Zip Code 5281
Retrieving Zip Code 5282
Retrieving Zip Code 5283
Retrieving Zip Code 5284
Retrieving Zip Code 5285
Retrieving Zip Code 5286
Retrieving Zip Code 5287
Retrieving Zip Code 5288
Retrieving Zip Code 5289
Retrieving Zip Code 5290
Retrieving Zip Code 5291
Retrieving Zip Code 5292
Retrieving Zip Code 5293
Retrieving Zip Code 5294
Retrieving Zip Code 5295
Retrieving Zip Code 5296
Retrieving Zip Code 5297
Retrieving Zip Code 5298
Retrieving Zip Code 5299
Retrieving Zip Code 5300
Retrieving Zip Code 5301
Retrieving Zip Code 5302
Retrieving Zip Code 5303
Retrieving Zip Code 5304
Retrieving Zip Code 5305
Retrieving Zip Code 5306
Retrieving Zip Code 5307
Retrieving Zip Code 5308
Retrieving Zip Code 5309
Retrieving Zip Code 5310
Retrieving Zip Code 5311
Retrieving Zip Code 5312
Retrieving Zip Code 5313
Retrieving Zip Code 5314
Retrieving Zip Code 5315
Retrieving Zip Code 5316
Retrieving Zip Code 5317
Retrieving Zip Code 5318
Retrieving Zip Code 5319
Retrieving Zip Code 5320
Retrieving Zip Code 5321
Retrieving Zip Code 5322
Retrieving Zip Code 5323
Retrieving Zip Code 5324
Retrieving Zip Code 5325
Retrieving Zip Code 5326
Retrieving Zip Code 5327
Retrieving Zip Code 5328
Retrieving Zip Code 5329
Retrieving Zip Code 5330
Retrieving Zip Code 5331
Retrieving Zip Code 5332
Retrieving Zip Code 5333
Retrieving Zip Code 5334
Retrieving Zip Code 5335
Retrieving Zip Code 5336
Retrieving Zip Code 5337
Retrieving Zip Code 5338
Retrieving Zip Code 5339
Retrieving Zip Code 5340
Retrieving Zip Code 5341
Retrieving Zip Code 5342
Retrieving Zip Code 5343
Retrieving Zip Code 5344
Retrieving Zip Code 5345
Retrieving Zip Code 5346
Retrieving Zip Code 5347
Retrieving Zip Code 5348
Retrieving Zip Code 5349
Retrieving Zip Code 5350
Retrieving Zip Code 5351
Retrieving Zip Code 5352
Retrieving Zip Code 5353
Retrieving Zip Code 5354
Retrieving Zip Code 5355
Retrieving Zip Code 5356
Retrieving Zip Code 5357
Retrieving Zip Code 5358
Retrieving Zip Code 5359
Retrieving Zip Code 5360
Retrieving Zip Code 5361
Retrieving Zip Code 5362
Retrieving Zip Code 5363
Retrieving Zip Code 5364
Retrieving Zip Code 5365
Retrieving Zip Code 5366
Retrieving Zip Code 5367
Retrieving Zip Code 5368
Retrieving Zip Code 5369
Retrieving Zip Code 5370
Retrieving Zip Code 5371
Retrieving Zip Code 5372
Retrieving Zip Code 5373
Retrieving Zip Code 5374
Retrieving Zip Code 5375
Retrieving Zip Code 5376
Retrieving Zip Code 5377
Retrieving Zip Code 5378
Retrieving Zip Code 5379
Retrieving Zip Code 5380
Retrieving Zip Code 5381
Retrieving Zip Code 5382
Retrieving Zip Code 5383
Retrieving Zip Code 5384
Retrieving Zip Code 5385
Retrieving Zip Code 5386
Retrieving Zip Code 5387
Retrieving Zip Code 5388
Retrieving Zip Code 5389
Retrieving Zip Code 5390
Retrieving Zip Code 5391
Retrieving Zip Code 5392
Retrieving Zip Code 5393
Retrieving Zip Code 5394
Retrieving Zip Code 5395
Retrieving Zip Code 5396
Retrieving Zip Code 5397
Retrieving Zip Code 5398
Retrieving Zip Code 5399
Retrieving Zip Code 5400
Retrieving Zip Code 5401
Retrieving Zip Code 5402
Retrieving Zip Code 5403
Retrieving Zip Code 5404
Retrieving Zip Code 5405
Retrieving Zip Code 5406
Retrieving Zip Code 5407
Retrieving Zip Code 5408
Retrieving Zip Code 5409
Retrieving Zip Code 5410
Retrieving Zip Code 5411
Retrieving Zip Code 5412
Retrieving Zip Code 5413
Retrieving Zip Code 5414
Retrieving Zip Code 5415
Retrieving Zip Code 5416
Retrieving Zip Code 5417
Retrieving Zip Code 5418
Retrieving Zip Code 5419
Retrieving Zip Code 5420
Retrieving Zip Code 5421
Retrieving Zip Code 5422
Retrieving Zip Code 5423
Retrieving Zip Code 5424
Retrieving Zip Code 5425
Retrieving Zip Code 5426
Retrieving Zip Code 5427
Retrieving Zip Code 5428
Retrieving Zip Code 5429
Retrieving Zip Code 5430
Retrieving Zip Code 5431
Retrieving Zip Code 5432
Retrieving Zip Code 5433
Retrieving Zip Code 5434
Retrieving Zip Code 5435
Retrieving Zip Code 5436
Retrieving Zip Code 5437
Retrieving Zip Code 5438
Retrieving Zip Code 5439
Retrieving Zip Code 5440
Retrieving Zip Code 5441
Retrieving Zip Code 5442
Retrieving Zip Code 5443
Retrieving Zip Code 5444
Retrieving Zip Code 5445
Retrieving Zip Code 5446
Retrieving Zip Code 5447
Retrieving Zip Code 5448
Retrieving Zip Code 5449
Retrieving Zip Code 5450
Retrieving Zip Code 5451
Retrieving Zip Code 5452
Retrieving Zip Code 5453
Retrieving Zip Code 5454
Retrieving Zip Code 5455
Retrieving Zip Code 5456
Retrieving Zip Code 5457
Retrieving Zip Code 5458
Retrieving Zip Code 5459
Retrieving Zip Code 5460
Retrieving Zip Code 5461
Retrieving Zip Code 5462
Retrieving Zip Code 5463
Retrieving Zip Code 5464
Retrieving Zip Code 5465
Retrieving Zip Code 5466
Retrieving Zip Code 5467
Retrieving Zip Code 5468
Retrieving Zip Code 5469
Retrieving Zip Code 5470
Retrieving Zip Code 5471
Retrieving Zip Code 5472
Retrieving Zip Code 5473
Retrieving Zip Code 5474
Retrieving Zip Code 5475
Retrieving Zip Code 5476
Retrieving Zip Code 5477
Retrieving Zip Code 5478
Retrieving Zip Code 5479
Retrieving Zip Code 5480
Retrieving Zip Code 5481
Retrieving Zip Code 5482
Retrieving Zip Code 5483
Retrieving Zip Code 5484
Retrieving Zip Code 5485
Retrieving Zip Code 5486
Retrieving Zip Code 5487
Retrieving Zip Code 5488
Retrieving Zip Code 5489
Retrieving Zip Code 5490
Retrieving Zip Code 5491
Retrieving Zip Code 5492
Retrieving Zip Code 5493
Retrieving Zip Code 5494
Retrieving Zip Code 5495
Retrieving Zip Code 5496
Retrieving Zip Code 5497
Retrieving Zip Code 5498
Retrieving Zip Code 5499
Retrieving Zip Code 5500
Retrieving Zip Code 5501
Retrieving Zip Code 5502
Retrieving Zip Code 5503
Retrieving Zip Code 5504
Retrieving Zip Code 5505
Retrieving Zip Code 5506
Retrieving Zip Code 5507
Retrieving Zip Code 5508
Retrieving Zip Code 5509
Retrieving Zip Code 5510
Retrieving Zip Code 5511
Retrieving Zip Code 5512
Retrieving Zip Code 5513
Retrieving Zip Code 5514
Retrieving Zip Code 5515
Retrieving Zip Code 5516
Retrieving Zip Code 5517
Retrieving Zip Code 5518
Retrieving Zip Code 5519
Retrieving Zip Code 5520
Retrieving Zip Code 5521
Retrieving Zip Code 5522
Retrieving Zip Code 5523
Retrieving Zip Code 5524
Retrieving Zip Code 5525
Retrieving Zip Code 5526
Retrieving Zip Code 5527
Retrieving Zip Code 5528
Retrieving Zip Code 5529
Retrieving Zip Code 5530
Retrieving Zip Code 5531
Retrieving Zip Code 5532
Retrieving Zip Code 5533
Retrieving Zip Code 5534
Retrieving Zip Code 5535
Retrieving Zip Code 5536
Retrieving Zip Code 5537
Retrieving Zip Code 5538
Retrieving Zip Code 5539
Retrieving Zip Code 5540
Retrieving Zip Code 5541
Retrieving Zip Code 5542
Retrieving Zip Code 5543
Retrieving Zip Code 5544
Retrieving Zip Code 5545
Retrieving Zip Code 5546
Retrieving Zip Code 5547
Retrieving Zip Code 5548
Retrieving Zip Code 5549
Retrieving Zip Code 5550
Retrieving Zip Code 5551
Retrieving Zip Code 5552
Retrieving Zip Code 5553
Retrieving Zip Code 5554
Retrieving Zip Code 5555
Retrieving Zip Code 5556
Retrieving Zip Code 5557
Retrieving Zip Code 5558
Retrieving Zip Code 5559
Retrieving Zip Code 5560
Retrieving Zip Code 5561
Retrieving Zip Code 5562
Retrieving Zip Code 5563
Retrieving Zip Code 5564
Retrieving Zip Code 5565
Retrieving Zip Code 5566
Retrieving Zip Code 5567
Retrieving Zip Code 5568
Retrieving Zip Code 5569
Retrieving Zip Code 5570
Retrieving Zip Code 5571
Retrieving Zip Code 5572
Retrieving Zip Code 5573
Retrieving Zip Code 5574
Retrieving Zip Code 5575
Retrieving Zip Code 5576
Retrieving Zip Code 5577
Retrieving Zip Code 5578
Retrieving Zip Code 5579
Retrieving Zip Code 5580
Retrieving Zip Code 5581
Retrieving Zip Code 5582
Retrieving Zip Code 5583
Retrieving Zip Code 5584
Retrieving Zip Code 5585
Retrieving Zip Code 5586
Retrieving Zip Code 5587
Retrieving Zip Code 5588
Retrieving Zip Code 5589
Retrieving Zip Code 5590
Retrieving Zip Code 5591
Retrieving Zip Code 5592
Retrieving Zip Code 5593
Retrieving Zip Code 5594
Retrieving Zip Code 5595
Retrieving Zip Code 5596
Retrieving Zip Code 5597
Retrieving Zip Code 5598
Retrieving Zip Code 5599
Retrieving Zip Code 5600
Retrieving Zip Code 5601
Retrieving Zip Code 5602
Retrieving Zip Code 5603
Retrieving Zip Code 5604
Retrieving Zip Code 5605
Retrieving Zip Code 5606
Retrieving Zip Code 5607
Retrieving Zip Code 5608
Retrieving Zip Code 5609
Retrieving Zip Code 5610
Retrieving Zip Code 5611
Retrieving Zip Code 5612
Retrieving Zip Code 5613
Retrieving Zip Code 5614
Retrieving Zip Code 5615
Retrieving Zip Code 5616
Retrieving Zip Code 5617
Retrieving Zip Code 5618
Retrieving Zip Code 5619
Retrieving Zip Code 5620
Retrieving Zip Code 5621
Retrieving Zip Code 5622
Retrieving Zip Code 5623
Retrieving Zip Code 5624
Retrieving Zip Code 5625
Retrieving Zip Code 5626
Retrieving Zip Code 5627
Retrieving Zip Code 5628
Retrieving Zip Code 5629
Retrieving Zip Code 5630
Retrieving Zip Code 5631
Retrieving Zip Code 5632
Retrieving Zip Code 5633
Retrieving Zip Code 5634
Retrieving Zip Code 5635
Retrieving Zip Code 5636
Retrieving Zip Code 5637
Retrieving Zip Code 5638
Retrieving Zip Code 5639
Retrieving Zip Code 5640
Retrieving Zip Code 5641
Retrieving Zip Code 5642
Retrieving Zip Code 5643
Retrieving Zip Code 5644
Retrieving Zip Code 5645
Retrieving Zip Code 5646
Retrieving Zip Code 5647
Retrieving Zip Code 5648
Retrieving Zip Code 5649
Retrieving Zip Code 5650
Retrieving Zip Code 5651
Retrieving Zip Code 5652
Retrieving Zip Code 5653
Retrieving Zip Code 5654
Retrieving Zip Code 5655
Retrieving Zip Code 5656
Retrieving Zip Code 5657
Retrieving Zip Code 5658
Retrieving Zip Code 5659
Retrieving Zip Code 5660
Retrieving Zip Code 5661
Retrieving Zip Code 5662
Retrieving Zip Code 5663
Retrieving Zip Code 5664
Retrieving Zip Code 5665
Retrieving Zip Code 5666
Retrieving Zip Code 5667
Retrieving Zip Code 5668
Retrieving Zip Code 5669
Retrieving Zip Code 5670
Retrieving Zip Code 5671
Retrieving Zip Code 5672
Retrieving Zip Code 5673
Retrieving Zip Code 5674
Retrieving Zip Code 5675
Retrieving Zip Code 5676
Retrieving Zip Code 5677
Retrieving Zip Code 5678
Retrieving Zip Code 5679
Retrieving Zip Code 5680
Retrieving Zip Code 5681
Retrieving Zip Code 5682
Retrieving Zip Code 5683
Retrieving Zip Code 5684
Retrieving Zip Code 5685
Retrieving Zip Code 5686
Retrieving Zip Code 5687
Retrieving Zip Code 5688
Retrieving Zip Code 5689
Retrieving Zip Code 5690
Retrieving Zip Code 5691
Retrieving Zip Code 5692
Retrieving Zip Code 5693
Retrieving Zip Code 5694
Retrieving Zip Code 5695
Retrieving Zip Code 5696
Retrieving Zip Code 5697
Retrieving Zip Code 5698
Retrieving Zip Code 5699
Retrieving Zip Code 5700
Retrieving Zip Code 5701
Retrieving Zip Code 5702
Retrieving Zip Code 5703
Retrieving Zip Code 5704
Retrieving Zip Code 5705
Retrieving Zip Code 5706
Retrieving Zip Code 5707
Retrieving Zip Code 5708
Retrieving Zip Code 5709
Retrieving Zip Code 5710
Retrieving Zip Code 5711
Retrieving Zip Code 5712
Retrieving Zip Code 5713
Retrieving Zip Code 5714
Retrieving Zip Code 5715
Retrieving Zip Code 5716
Retrieving Zip Code 5717
Retrieving Zip Code 5718
Retrieving Zip Code 5719
Retrieving Zip Code 5720
Retrieving Zip Code 5721
Retrieving Zip Code 5722
Retrieving Zip Code 5723
Retrieving Zip Code 5724
Retrieving Zip Code 5725
Retrieving Zip Code 5726
Retrieving Zip Code 5727
Retrieving Zip Code 5728
Retrieving Zip Code 5729
Retrieving Zip Code 5730
Retrieving Zip Code 5731
Retrieving Zip Code 5732
Retrieving Zip Code 5733
Retrieving Zip Code 5734
Retrieving Zip Code 5735
Retrieving Zip Code 5736
Retrieving Zip Code 5737
Retrieving Zip Code 5738
Retrieving Zip Code 5739
Retrieving Zip Code 5740
Retrieving Zip Code 5741
Retrieving Zip Code 5742
Retrieving Zip Code 5743
Retrieving Zip Code 5744
Retrieving Zip Code 5745
Retrieving Zip Code 5746
Retrieving Zip Code 5747
Retrieving Zip Code 5748
Retrieving Zip Code 5749
Retrieving Zip Code 5750
Retrieving Zip Code 5751
Retrieving Zip Code 5752
Retrieving Zip Code 5753
Retrieving Zip Code 5754
Retrieving Zip Code 5755
Retrieving Zip Code 5756
Retrieving Zip Code 5757
Retrieving Zip Code 5758
Retrieving Zip Code 5759
Retrieving Zip Code 5760
Retrieving Zip Code 5761
Retrieving Zip Code 5762
Retrieving Zip Code 5763
Retrieving Zip Code 5764
Retrieving Zip Code 5765
Retrieving Zip Code 5766
Retrieving Zip Code 5767
Retrieving Zip Code 5768
Retrieving Zip Code 5769
Retrieving Zip Code 5770
Retrieving Zip Code 5771
Retrieving Zip Code 5772
Retrieving Zip Code 5773
Retrieving Zip Code 5774
Retrieving Zip Code 5775
Retrieving Zip Code 5776
Retrieving Zip Code 5777
Retrieving Zip Code 5778
Retrieving Zip Code 5779
Retrieving Zip Code 5780
Retrieving Zip Code 5781
Retrieving Zip Code 5782
Retrieving Zip Code 5783
Retrieving Zip Code 5784
Retrieving Zip Code 5785
Retrieving Zip Code 5786
Retrieving Zip Code 5787
Retrieving Zip Code 5788
Retrieving Zip Code 5789
Retrieving Zip Code 5790
Retrieving Zip Code 5791
Retrieving Zip Code 5792
Retrieving Zip Code 5793
Retrieving Zip Code 5794
Retrieving Zip Code 5795
Retrieving Zip Code 5796
Retrieving Zip Code 5797
Retrieving Zip Code 5798
Retrieving Zip Code 5799
Retrieving Zip Code 5800
Retrieving Zip Code 5801
Retrieving Zip Code 5802
Retrieving Zip Code 5803
Retrieving Zip Code 5804
Retrieving Zip Code 5805
Retrieving Zip Code 5806
Retrieving Zip Code 5807
Retrieving Zip Code 5808
Retrieving Zip Code 5809
Retrieving Zip Code 5810
Retrieving Zip Code 5811
Retrieving Zip Code 5812
Retrieving Zip Code 5813
Retrieving Zip Code 5814
Retrieving Zip Code 5815
Retrieving Zip Code 5816
Retrieving Zip Code 5817
Retrieving Zip Code 5818
Retrieving Zip Code 5819
Retrieving Zip Code 5820
Retrieving Zip Code 5821
Retrieving Zip Code 5822
Retrieving Zip Code 5823
Retrieving Zip Code 5824
Retrieving Zip Code 5825
Retrieving Zip Code 5826
Retrieving Zip Code 5827
Retrieving Zip Code 5828
Retrieving Zip Code 5829
Retrieving Zip Code 5830
Retrieving Zip Code 5831
Retrieving Zip Code 5832
Retrieving Zip Code 5833
Retrieving Zip Code 5834
Retrieving Zip Code 5835
Retrieving Zip Code 5836
Retrieving Zip Code 5837
Retrieving Zip Code 5838
Retrieving Zip Code 5839
Retrieving Zip Code 5840
Retrieving Zip Code 5841
Retrieving Zip Code 5842
Retrieving Zip Code 5843
Retrieving Zip Code 5844
Retrieving Zip Code 5845
Retrieving Zip Code 5846
Retrieving Zip Code 5847
Retrieving Zip Code 5848
Retrieving Zip Code 5849
Retrieving Zip Code 5850
Retrieving Zip Code 5851
Retrieving Zip Code 5852
Retrieving Zip Code 5853
Retrieving Zip Code 5854
Retrieving Zip Code 5855
Retrieving Zip Code 5856
Retrieving Zip Code 5857
Retrieving Zip Code 5858
Retrieving Zip Code 5859
Retrieving Zip Code 5860
Retrieving Zip Code 5861
Retrieving Zip Code 5862
Retrieving Zip Code 5863
Retrieving Zip Code 5864
Retrieving Zip Code 5865
Retrieving Zip Code 5866
Retrieving Zip Code 5867
Retrieving Zip Code 5868
Retrieving Zip Code 5869
Retrieving Zip Code 5870
Retrieving Zip Code 5871
Retrieving Zip Code 5872
Retrieving Zip Code 5873
Retrieving Zip Code 5874
Retrieving Zip Code 5875
Retrieving Zip Code 5876
Retrieving Zip Code 5877
Retrieving Zip Code 5878
Retrieving Zip Code 5879
Retrieving Zip Code 5880
Retrieving Zip Code 5881
Retrieving Zip Code 5882
Retrieving Zip Code 5883
Retrieving Zip Code 5884
Retrieving Zip Code 5885
Retrieving Zip Code 5886
Retrieving Zip Code 5887
Retrieving Zip Code 5888
Retrieving Zip Code 5889
Retrieving Zip Code 5890
Retrieving Zip Code 5891
Retrieving Zip Code 5892
Retrieving Zip Code 5893
Retrieving Zip Code 5894
Retrieving Zip Code 5895
Retrieving Zip Code 5896
Retrieving Zip Code 5897
Retrieving Zip Code 5898
Retrieving Zip Code 5899
Retrieving Zip Code 5900
Retrieving Zip Code 5901
Retrieving Zip Code 5902
Retrieving Zip Code 5903
Retrieving Zip Code 5904
Retrieving Zip Code 5905
Retrieving Zip Code 5906
Retrieving Zip Code 5907
Retrieving Zip Code 5908
Retrieving Zip Code 5909
Retrieving Zip Code 5910
Retrieving Zip Code 5911
Retrieving Zip Code 5912
Retrieving Zip Code 5913
Retrieving Zip Code 5914
Retrieving Zip Code 5915
Retrieving Zip Code 5916
Retrieving Zip Code 5917
Retrieving Zip Code 5918
Retrieving Zip Code 5919
Retrieving Zip Code 5920
Retrieving Zip Code 5921
Retrieving Zip Code 5922
Retrieving Zip Code 5923
Retrieving Zip Code 5924
Retrieving Zip Code 5925
Retrieving Zip Code 5926
Retrieving Zip Code 5927
Retrieving Zip Code 5928
Retrieving Zip Code 5929
Retrieving Zip Code 5930
Retrieving Zip Code 5931
Retrieving Zip Code 5932
Retrieving Zip Code 5933
Retrieving Zip Code 5934
Retrieving Zip Code 5935
Retrieving Zip Code 5936
Retrieving Zip Code 5937
Retrieving Zip Code 5938
Retrieving Zip Code 5939
Retrieving Zip Code 5940
Retrieving Zip Code 5941
Retrieving Zip Code 5942
Retrieving Zip Code 5943
Retrieving Zip Code 5944
Retrieving Zip Code 5945
Retrieving Zip Code 5946
Retrieving Zip Code 5947
Retrieving Zip Code 5948
Retrieving Zip Code 5949
Retrieving Zip Code 5950
   user  system elapsed 
 48.477 159.656 232.834 

Feature engineering.

Inspecting incidences of consecutive Stop_IDs. This is done because investigation showed that many conseutive events occurr at the same Stop_ID, but with various Dwell_Times, Odometer_Distances, etc. All of which affect calculations and analyses.

Create data on the runs (consecutive Stop_IDs).

StopID_Runs <- rle(AllDays_StopIDNew$StopID_Clean)
StopID_Runs$ends <- cumsum(StopID_Runs$lengths)
StopID_Runs$starts <- ifelse(is.na(lag(StopID_Runs$ends)
                                  ),
                             1,
                             lag(StopID_Runs$ends) + 1
                            )
str(StopID_Runs)
List of 4
 $ lengths: int [1:2809529] 2 1 1 1 1 2 1 1 1 1 ...
 $ values : chr [1:2809529] "5004572" "5004573" "5002210" "5002209" ...
 $ ends   : int [1:2809529] 2 3 4 5 6 8 9 10 11 12 ...
 $ starts : num [1:2809529] 1 3 4 5 6 7 9 10 11 12 ...
 - attr(*, "class")= chr "rle"
# class(StopID_Runs)
# 
# StopID_Runs_df <- data.frame(unclass(StopID_Runs))
# str(StopID_Runs_df)
# class(StopID_Runs_df)
# rm(StopID_Runs_df)

Trying to link data on RunsGroups with the original data (AllDays_Sorted). The goal is to select only one record per RunsGroup - that being the record with the longest Dwell_Time.

I attempted this computation using both data.frames (dplyr) and data.tables (data.table). However, with 2,809,062 rows in one dataset and 3,119,443 rows in the other dataset, the current computation time is over 5 days…so I’m trying a different strategy to only select the first record in a run.

# Create a RunsGroup variable for each run
# StopID_Runs_df$RunsGroup <- paste0("g", seq(1:nrow(StopID_Runs_df)
#                                            )
#                                   )
# 
# str(StopID_Runs_df)
# head(StopID_Runs_df, 25)
# tail(StopID_Runs_df, 25)
# 
# StopID_Runs_df <- StopID_Runs_df %>% 
#   mutate(RowNum = row_number()
#         )
# 
# str(StopID_Runs_df)
# head(StopID_Runs_df, 25)
# tail(StopID_Runs_df, 25)
# 
# 
# # Converting to data.tables for, hopefully, improved performance (speed) in computation
# StopID_Runs_dt <- data.table(StopID_Runs_df)
# setkey(StopID_Runs_dt, RowNum)
# str(StopID_Runs_dt)
# 
# AllDays_Sorted_dt <- data.table(AllDays_Sorted)
# setkey(AllDays_Sorted_dt, RowNum_OG)
# str(AllDays_Sorted_dt)
# # rm(AllDays_Sorted_dt)
# 
# 
# # Actual loop to perform the computations and link to original data (AllDays_Sorted_dt)
# GroupData <- list()
# for(i in 1:nrow(StopID_Runs_dt)
#    ) {
#   assign(paste0("group_", i),
#            StopID_Runs_dt[RowNum == i, RunsGroup]
#           )
# 
#     #####  The code below is the same code as above, but done with dplyr  #####
# 
#     # assign(paste0("group_", i),
#   #        filter(StopID_Runs_df,
#   #               RowNum == i
#   #              ) %>% 
#   #          select(RunsGroup)
#   #       )
# 
#   assign(paste0("group_", i, "_start"),
#          StopID_Runs_dt[RowNum == i, starts]
#         )
# 
#   assign(paste0("group_", i, "_end"),
#          StopID_Runs_dt[RowNum == i, ends]
#         )
# 
#   assign(paste0("group_", i, "_rows"),
#          AllDays_Sorted_dt[RowNum_OG >= as.numeric(get(paste0("group_", i, "_start")
#                                                       )
#                                                   ) &
#                            RowNum_OG <= as.numeric(get(paste0("group_", i, "_end")
#                                                       )
#                                                   ),
#                            RunsGroup := as.character(get(paste0("group_", i)
#                                                         )
#                                                     )
#                           ]
# 
#     #####  The code below is the same as the code above, but done with dplyr  #####
# 
#          # filter(AllDays_Sorted,
#          #        between(RowNum_OG,
#          #                as.numeric(get(paste0("group_", i, "_start")
#          #                              )
#          #                          ),
#          #                as.numeric(get(paste0("group_", i, "_end")
#          #                              )
#          #                          )
#          #               )
#          #       ) %>% 
#          #   mutate(RunsGroup = as.character(get(paste0("group_", i)
#          #                                     )
#          #                                 )
#          #        )
#         )
# 
#   GroupData[[i]] <- get(paste0("group_", i, "_rows"))
# 
#   message("Processing Group ", i, " of 2,809,062")
# }
# 
# 
# GroupData_df <- rbind.fill(GroupData)
# str(GroupData_df)
# head(GroupData_df)
# tail(GroupData_df)
# # rm(GroupData_df)
# 
# 
# group_1
# group_1_start
# group_1_end
# group_1_rows
# group_2_rows
# group_3_rows
# group_50_rows
# str(group_50_rows)
# group_2809062_rows
# GroupData[[1]]
# GroupData[[50]]
# 
# 
# #####  Testing Area (Below)  #####
# #####  Testing Area (Below)  #####
# #####  Testing Area (Below)  #####
# 
# # head(StopID_Runs$starts, 20)
# # head(AllDays_NewOrder$Stop_ID, 20)
# # 
# # 
# # dat <- as.data.frame(c(1,1,7,7,7,9,6,8,2,2,2,1,1,1,1,1))
# # colnames(dat)[1] <- "dat"
# # r <- rle(dat$dat)
# # dat$run <- rep(r$lengths, r$lengths)
# # dat$runLag <- lag(dat$run)
# # dat$cond <- rep(r$values, r$lengths)
# # dat
# # View(dat)

When consecutive Stop_ID occurrs, only take the first occurrence. This is done because the computation time to select only the record with the longest Dwell_Time for each run was too long (over 5 days).

This is probably less than ideal with regards to Dwell_Time, but should not make much difference for calculations of travel time, speed, etc.

AllDays_FirstStopID <- AllDays_StopIDNew[StopID_Runs$starts, ]
dim(AllDays_StopIDNew)
[1] 3119443      22
dim(AllDays_FirstStopID)
[1] 2809529      22
nrow(AllDays_StopIDNew) - nrow(AllDays_FirstStopID)
[1] 309914
rm(AllDays_StopIDNew)
rm(StopID_Runs)
str(AllDays_FirstStopID)
'data.frame':   2809529 obs. of  22 variables:
 $ group            : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID           : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route            : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt         : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction  : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence    : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc        : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type       : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description: Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time       : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time   : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time       : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time       : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance: int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude         : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude        : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading          : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG        : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New       : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean     : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...

Feature engineering.

Creating new variables.

AllDays_AddVars <- mutate(AllDays_FirstStopID,
                          Odometer_Distance_Mi = Odometer_Distance / 5280, #5,280 feet in 1 mile
                          Dwell_Time2 = as.numeric(Departure_Time - Event_Time),
                          Event_Time_Yr = as.integer(year(Event_Time)),
                          Event_Time_Mth = as.integer(month(Event_Time)),
                          Event_Time_Date = day(Event_Time),
                          Event_Time_Day = wday(Event_Time, label = TRUE),
                          Event_Time_Hr = hour(Event_Time),
                          Event_Time_Min = minute(Event_Time),
                          Event_Time_HrGroup = factor(ifelse(Event_Time_Hr < 3,
                                                             "Group0_2",
                                                      ifelse(Event_Time_Hr < 6,
                                                             "Group3_5",
                                                      ifelse(Event_Time_Hr < 9,
                                                             "Group6_8",
                                                      ifelse(Event_Time_Hr < 12,
                                                             "Group9_11",
                                                      ifelse(Event_Time_Hr < 15,
                                                             "Group12_14",
                                                      ifelse(Event_Time_Hr < 18,
                                                             "Group15_17",
                                                      ifelse(Event_Time_Hr < 21,
                                                             "Group18_20",
                                                      ifelse(Event_Time_Hr < 24,
                                                             "Group21_23"
                                                            )))))))),
                                                         levels = c("Group0_2",
                                                                    "Group3_5",
                                                                    "Group6_8",
                                                                    "Group9_11",
                                                                    "Group12_14",
                                                                    "Group15_17",
                                                                    "Group18_20",
                                                                    "Group21_23"
                                                                   ),
                                                         ordered = TRUE
                                                     )
                         )
rm(AllDays_FirstStopID)
str(AllDays_AddVars)
'data.frame':   2809529 obs. of  31 variables:
 $ group               : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID              : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route               : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt            : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction     : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence       : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID             : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc           : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type          : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description   : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time          : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time      : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time          : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time          : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance   : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude            : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude           : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading             : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG           : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New          : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean        : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator    : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi: num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2         : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr       : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth      : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date     : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day      : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr       : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min      : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup  : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
# group_by(AllDays_AddVars,
#          Event_Time_HrGroup
#         ) %>% 
#   summarise(Cnts = n()
#            )
# View(head(filter(AllDays_AddVars,
#                  Event_Time_Hr == 0
#                 ),
#           50
#          )
#     )
# View(head(AllDays_AddVars, 50))

Feature engineering.

Creating more variables. Creating a BusEvent row number for future identification purposes. Then, creating various variables to analyze distance traveled and speed.

AllDays_BusDay <- group_by(AllDays_AddVars,
                           Bus_ID,
                           Event_Time_Date
                          ) %>% 
  mutate(BusDay_EventNum = row_number(),  # used to identify Bus movements on a particular date
         
         Route_Lag1 = lag(Route),  # used in future analyses to identify Route changes
         RouteAlt_Lag1 = lag(RouteAlt),  # used in future analyses to identify RouteAlt (direction) changes
         
         Odometer_Distance_Lag1 = lag(Odometer_Distance),
         
         Latitude_L1 = lag(Latitude),
         Longitude_L1 = lag(Longitude),
         # Lat_Radian = Latitude*pi/180,
         # Long_Radian = Longitude*pi/180,
         # Lat_Radian_L1 = lag(Lat_Radian),
         # Long_Radian_L1 = lag(Long_Radian),
         
         # accounting for potential negative distances
         TravelDistance_Ft = ifelse(Odometer_Distance > Odometer_Distance_Lag1,
                                    Odometer_Distance - Odometer_Distance_Lag1,
                                    NA
                                   ),
         TravelDistance_Mi = TravelDistance_Ft / 5280, #5,280 feet in 1 mile
         
         # TravelDistance_Mi2 = gcd.hf(long1 = Long_Radian_L1,
         #                             lat1 = Lat_Radian_L1,
         #                             long2 = Long_Radian,
         #                             lat2 = Lat_Radian
         #                            ),
         
         TravelDistance_Mi_Hvrs = 
                              # ifelse((is.na(Longitude_L1) | is.na(Latitude_L1)
                              #        ),
                              #        NA,
                              distHaversine(cbind(Longitude_L1, Latitude_L1),
                                            cbind(Longitude, Latitude)
                                           ) * 0.000621371, # 0.000621371 miles = 1 meter
         
         # accounting for potential negative times
         TravelTime_Sec = as.numeric(ifelse(Event_Time > lag(Departure_Time),
                                            Event_Time - lag(Departure_Time),
                                            NA
                                           )
                                    ),
         TravelTime_Hr = TravelTime_Sec / 3600, # 3,600 seconds in 1 hour
         
         # accounting for potential negative or zero travel times
         SpeedAvg_Mph = ifelse(TravelTime_Hr > 0,
                               TravelDistance_Mi / TravelTime_Hr,
                               NA
                              ),
         
         Start_ID = lag(StopID_Clean),
         Start_Desc = lag(Stop_Desc),
         StartStop_ID = ifelse(is.na(Start_ID),
                               paste("NULL", StopID_Clean, sep = "--"),
                               paste(Start_ID, StopID_Clean, sep = "--")
                              )
        ) %>% 
  as.data.frame()
rm(AllDays_AddVars)
str(AllDays_BusDay)
'data.frame':   2809529 obs. of  46 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
# summary(AllDays_BusDay)
# View(tail(AllDays_BusDay, 50))

Inspecting for issues with StartStop_ID (where the value is either NA or contains NULL). They ONLY exist when BusDay_EventNum = 1 (which is by design). So everything looks OK.

View(group_by(AllDays_BusDay,
              StartStop_ID
             ) %>% 
       summarise(
         Cnt = n()
       ) %>% 
       arrange(desc(Cnt)
              )
    )
View(filter(AllDays_BusDay,
            (is.na(StartStop_ID) |
              str_detect(StartStop_ID, "NULL")
            ) &
              BusDay_EventNum != 1
           )
    )

Stats (quantiles) overall for TravelDistance_Mi.

Quantiles_dt <- AllDays_BusDay %>% 
  mutate(TD_Mi_q2 = quantile(x = TravelDistance_Mi, probs = 0.02, na.rm = TRUE),
         TD_Mi_q98 = quantile(x = TravelDistance_Mi, probs = 0.98, na.rm = TRUE),
         TT_Sec_q2 = quantile(x = TravelTime_Sec, probs = 0.02, na.rm = TRUE),
         TT_Sec_q98 = quantile(x = TravelTime_Sec, probs = 0.98, na.rm = TRUE),
         TT_Hr_q2 = quantile(x = TravelTime_Hr, probs = 0.02, na.rm = TRUE),
         TT_Hr_q98 = quantile(x = TravelTime_Hr, probs = 0.98, na.rm = TRUE)
        ) %>% 
  data.table()
Stats <- Quantiles_dt %>% 
  mutate(TD_Mi_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_Mean_F = mean(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98],
                             na.rm = TRUE
                            ),
         TD_Mi_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_Med_F = median(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98],
                              na.rm = TRUE
                             ),
         TD_Mi_Cnt = sum(!is.na(TravelDistance_Mi)
                        ),
         TD_Mi_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_q2 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_q98]
                                 )
                          ),
            
         TT_Sec_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_Mean_F = mean(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98],
                              na.rm = TRUE
                             ),
         TT_Sec_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_Med_F = median(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98],
                               na.rm = TRUE
                              ),
         TT_Sec_Cnt = sum(!is.na(TravelTime_Sec)
                         ),
         TT_Sec_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_q2 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_q98]
                                   )
                           ),
         TT_Hr_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_Mean_F = mean(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98],
                             na.rm = TRUE
                            ),
         TT_Hr_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_Med_F = median(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98],
                              na.rm = TRUE
                             ),
         TT_Hr_Cnt = sum(!is.na(TravelTime_Hr)
                        ),
         TT_Hr_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_q2 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_q98]
                                 )
                          )
        ) %>% 
  data.frame()
rm(AllDays_BusDay)
rm(Quantiles_dt)
str(Stats)
'data.frame':   2809529 obs. of  70 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
# View(head(Stats, 50))

Stats for StartStop_ID.

Quantiles_SS_dt <- group_by(Stats,
                            StartStop_ID
                           ) %>% 
  mutate(TD_Mi_SS_q5 = quantile(x = TravelDistance_Mi, probs = 0.05, na.rm = TRUE),
         TD_Mi_SS_q95 = quantile(x = TravelDistance_Mi, probs = 0.95, na.rm = TRUE),
         TT_Sec_SS_q5 = quantile(x = TravelTime_Sec, probs = 0.05, na.rm = TRUE),
         TT_Sec_SS_q95 = quantile(x = TravelTime_Sec, probs = 0.95, na.rm = TRUE),
         TT_Hr_SS_q5 = quantile(x = TravelTime_Hr, probs = 0.05, na.rm = TRUE),
         TT_Hr_SS_q95 = quantile(x = TravelTime_Hr, probs = 0.95, na.rm = TRUE)
        ) %>% 
  data.table()
Stats_StSt <- group_by(Quantiles_SS_dt,
                       StartStop_ID
                      ) %>% 
  mutate(TD_Mi_SS_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SS_Mean_F = mean(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95],
                                na.rm = TRUE
                               ),
         TD_Mi_SS_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SS_Med_F = median(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95],
                                 na.rm = TRUE
                                ),
         TD_Mi_SS_Cnt = sum(!is.na(TravelDistance_Mi)
                           ),
         TD_Mi_SS_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_SS_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SS_q95]
                                    )
                             ),
            
         TT_Sec_SS_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SS_Mean_F = mean(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95],
                                 na.rm = TRUE
                                ),
         TT_Sec_SS_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SS_Med_F = median(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95],
                                  na.rm = TRUE
                                 ),
         TT_Sec_SS_Cnt = sum(!is.na(TravelTime_Sec)),
         TT_Sec_SS_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_SS_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SS_q95]
                                     )
                              ),
         TT_Hr_SS_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SS_Mean_F = mean(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95],
                                na.rm = TRUE
                               ),
         TT_Hr_SS_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SS_Med_F = median(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95],
                                 na.rm = TRUE
                                ),
         TT_Hr_SS_Cnt = sum(!is.na(TravelTime_Hr)),
         TT_Hr_SS_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_SS_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SS_q95]
                                    )
                             )
        ) %>% 
  data.frame()
rm(Stats)
rm(Quantiles_SS_dt)
str(Stats_StSt)
'data.frame':   2809529 obs. of  94 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SS_Med          : num  NA 0.0621 0.0103 0.0182 0.0503 ...
 $ TT_Hr_SS_Med_F        : num  NA 0.0621 0.0103 0.0182 NA ...
 $ TT_Hr_SS_Cnt          : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Hr_SS_Cnt_F        : int  0 12 1 2 0 156 18 127 128 9 ...
# View(head(Stats_StSt, 50))

Stats for StartStop_ID with Event_Time_HrGroup.

Quantiles_SSHG_dt <- group_by(Stats_StSt,
                              StartStop_ID,
                              Event_Time_HrGroup
                             ) %>% 
  mutate(TD_Mi_SSHG_q5 = quantile(x = TravelDistance_Mi, probs = 0.05, na.rm = TRUE),
         TD_Mi_SSHG_q95 = quantile(x = TravelDistance_Mi, probs = 0.95, na.rm = TRUE),
         TT_Sec_SSHG_q5 = quantile(x = TravelTime_Sec, probs = 0.05, na.rm = TRUE),
         TT_Sec_SSHG_q95 = quantile(x = TravelTime_Sec, probs = 0.95, na.rm = TRUE),
         TT_Hr_SSHG_q5 = quantile(x = TravelTime_Hr, probs = 0.05, na.rm = TRUE),
         TT_Hr_SSHG_q95 = quantile(x = TravelTime_Hr, probs = 0.95, na.rm = TRUE)
        ) %>% 
  data.table()
Stats_StSt_HrGrp <- group_by(Quantiles_SSHG_dt,
                             StartStop_ID,
                             Event_Time_HrGroup
                            ) %>% 
  mutate(TD_Mi_SSHG_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SSHG_Mean_F = mean(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95],
                                  na.rm = TRUE
                                 ),
         TD_Mi_SSHG_Med = median(TravelDistance_Mi, na.rm = TRUE),
         TD_Mi_SSHG_Med_F = median(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TD_Mi_SSHG_Cnt = sum(!is.na(TravelDistance_Mi)
                             ),
         TD_Mi_SSHG_Cnt_F = sum(!is.na(TravelDistance_Mi[TD_Mi_SSHG_q5 <= TravelDistance_Mi & TravelDistance_Mi <= TD_Mi_SSHG_q95]
                                      )
                               ),
            
         TT_Sec_SSHG_Mean = mean(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SSHG_Mean_F = mean(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TT_Sec_SSHG_Med = median(TravelTime_Sec, na.rm = TRUE),
         TT_Sec_SSHG_Med_F = median(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95],
                                    na.rm = TRUE
                                   ),
         TT_Sec_SSHG_Cnt = sum(!is.na(TravelTime_Sec)),
         TT_Sec_SSHG_Cnt_F = sum(!is.na(TravelTime_Sec[TT_Sec_SSHG_q5 <= TravelTime_Sec & TravelTime_Sec <= TT_Sec_SSHG_q95]
                                       )
                                ),
         TT_Hr_SSHG_Mean = mean(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SSHG_Mean_F = mean(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95],
                                  na.rm = TRUE
                                 ),
         TT_Hr_SSHG_Med = median(TravelTime_Hr, na.rm = TRUE),
         TT_Hr_SSHG_Med_F = median(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95],
                                   na.rm = TRUE
                                  ),
         TT_Hr_SSHG_Cnt = sum(!is.na(TravelTime_Hr)),
         TT_Hr_SSHG_Cnt_F = sum(!is.na(TravelTime_Hr[TT_Hr_SSHG_q5 <= TravelTime_Hr & TravelTime_Hr <= TT_Hr_SSHG_q95]
                                      )
                               )
        ) %>% 
  data.frame()
rm(Stats_StSt)
rm(Quantiles_SSHG_dt)
str(Stats_StSt_HrGrp)
'data.frame':   2809529 obs. of  118 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SS_Med          : num  NA 0.0621 0.0103 0.0182 0.0503 ...
 $ TT_Hr_SS_Med_F        : num  NA 0.0621 0.0103 0.0182 NA ...
 $ TT_Hr_SS_Cnt          : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Hr_SS_Cnt_F        : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Hr_SSHG_q5         : num  NA 0.01656 0.01028 0.00694 0.05278 ...
  [list output truncated]
# View(head(Stats_StSt_HrGrp, 50))

Feature engineering.

Creating a BusEventRoute row number, and a RouteAlt_Lag1 indicator for future identification purposes.

# rm(Quantiles_dt)
# rm(Quantiles_SS_dt)
# rm(AllDays_BusDay)
# rm(Quantiles_SSHG_dt)
# rm(Stats_StSt)
# AllDays_BusDayRoute <- group_by(Stats_StSt_HrGrp,
#                                 Bus_ID,
#                                 Event_Time_Date,
#                                 Route
#                                ) %>% 
#   mutate(RouteAlt_Lag2 = lag(RouteAlt)  # used in future analyses to identify RouteAlt (direction) changes
#          
#          # Odometer_Distance_Lag1 = lag(Odometer_Distance),
#          # 
#          # # accounting for potential negative distances
#          # TravelDistance_Ft = ifelse(Odometer_Distance >= Odometer_Distance_Lag1,
#          #                            Odometer_Distance - Odometer_Distance_Lag1,
#          #                            NA
#          #                           ),
#          # TravelDistance_Mi = TravelDistance_Ft / 5280, #5,280 feet in 1 mile
#          # 
#          # # accounting for potential negative times
#          # TravelTime_Sec = as.numeric(ifelse(Event_Time >= lag(Departure_Time),
#          #                                    Event_Time - lag(Departure_Time),
#          #                                    NA
#          #                                   )
#          #                            ),
#          # TravelTime_Hr = TravelTime_Sec / 3600, # 3,600 seconds in 1 hour
#          # 
#          # # accounting for potential negative or zero travel times
#          # SpeedAvg_Mph = ifelse(TravelTime_Hr > 0,
#          #                       TravelDistance_Mi / TravelTime_Hr,
#          #                       NA
#          #                      )
#         ) %>% 
#   data.frame()
# 
# rm(Stats_StSt_HrGrp)
# str(AllDays_BusDayRoute)

Feature engineering.

Calculating a variable to know if the RouteAlt changed. Could be useful in helping identifying weirdness in calculated distances and speeds.

# rm(Stats_StSt_HrGrp)
AllDays_DirChange <- Stats_StSt_HrGrp %>%  # AllDays_BusDayRoute %>% 
  mutate(RteChange = ifelse(Route == Route_Lag1,
                            "Same",
                            "Change"
                           ),
         RteChange2 = factor(ifelse(is.na(RteChange),
                                    "Change",
                                    RteChange
                                   )
                            ),
         DirChange = ifelse(RouteAlt == RouteAlt_Lag1,
                            "Same",
                            "Change"
                           ),
         DirChange2 = factor(ifelse(is.na(DirChange),
                                    "Change",
                                    DirChange
                                   )
                            )
        )
# rm(AllDays_BusDayRoute)
rm(Stats_StSt_HrGrp)
str(AllDays_DirChange)
'data.frame':   2809529 obs. of  122 variables:
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Stop_ID               : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ StopID_New            : int  NA NA NA NA NA NA NA NA NA NA ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Route_Lag1            : chr  NA "S80" "S80" "S80" ...
 $ RouteAlt_Lag1         : Factor w/ 14 levels "1","10","11",..: NA 1 1 1 1 1 1 6 6 6 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Latitude_L1           : num  NA 38.8 38.8 38.8 38.8 ...
 $ Longitude_L1          : num  NA -77.2 -77.2 -77.2 -77.2 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph          : num  NA 6.05 23.57 100.83 3.44 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_Med             : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Med_F           : num  0.0108 0.0108 0.0108 0.0108 0.0108 ...
 $ TT_Hr_Cnt             : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Hr_Cnt_F           : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
 $ TT_Hr_SS_Med          : num  NA 0.0621 0.0103 0.0182 0.0503 ...
 $ TT_Hr_SS_Med_F        : num  NA 0.0621 0.0103 0.0182 NA ...
 $ TT_Hr_SS_Cnt          : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Hr_SS_Cnt_F        : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Hr_SSHG_q5         : num  NA 0.01656 0.01028 0.00694 0.05278 ...
  [list output truncated]
View(filter(AllDays_DirChange,
            between(RowNum_OG, 2570060, 2570080)
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
             )
    )

Re-ordering the variables to ease with comprehension.

AllDays_NewOrder <-  select(AllDays_DirChange,
                            RowNum_OG,
                            group,
                            StartStop_ID,
                            BusDay_EventNum,
                            Bus_ID,
                            Route,
                            RteChange2,
                            RouteAlt,
                            # RouteAlt_Lag1,
                            DirChange2,
                            Route_Direction,
                            Stop_Sequence,
                            Start_ID,
                            Start_Desc,
                            # Stop_ID,
                            StopID_Clean,
                            StopID_Indicator,
                            Stop_Desc,
                            Event_Type,
                            Event_Description,
                            Event_Time_Yr,
                            Event_Time_Mth,
                            Event_Time_Date,
                            Event_Time_Day,
                            Event_Time_Hr,
                            Event_Time_HrGroup,
                            Event_Time_Min,
                            Event_Time,
                            Departure_Time,
                            Dwell_Time,
                            Dwell_Time2,
                            Delta_Time,
                            Latitude,
                            Longitude,
                            Heading,
                            Odometer_Distance,
                            Odometer_Distance_Lag1,
                            Odometer_Distance_Mi,
                            TravelDistance_Ft,
                            TravelDistance_Mi,
                            TravelDistance_Mi_Hvrs,
                            TD_Mi_q2,
                            TD_Mi_q98,
                            TD_Mi_SS_q5,
                            TD_Mi_SS_q95,
                            TD_Mi_SSHG_q5,
                            TD_Mi_SSHG_q95,
                            TD_Mi_Mean,
                            TD_Mi_Mean_F,
                            TD_Mi_SS_Mean,
                            TD_Mi_SS_Mean_F,
                            TD_Mi_SSHG_Mean,
                            TD_Mi_SSHG_Mean_F,
                            TD_Mi_Med,
                            TD_Mi_Med_F,
                            TD_Mi_SS_Med,
                            TD_Mi_SS_Med_F,
                            TD_Mi_SSHG_Med,
                            TD_Mi_SSHG_Med_F,
                            TD_Mi_Cnt,
                            TD_Mi_Cnt_F,
                            TD_Mi_SS_Cnt,
                            TD_Mi_SS_Cnt_F,
                            TD_Mi_SSHG_Cnt,
                            TD_Mi_SSHG_Cnt_F,
                            TravelTime_Sec,
                            TT_Sec_q2,
                            TT_Sec_q98,
                            TT_Sec_SS_q5,
                            TT_Sec_SS_q95,
                            TT_Sec_SSHG_q5,
                            TT_Sec_SSHG_q95,
                            TT_Sec_Mean,
                            TT_Sec_Mean_F,
                            TT_Sec_SS_Mean,
                            TT_Sec_SS_Mean_F,
                            TT_Sec_SSHG_Mean,
                            TT_Sec_SSHG_Mean_F,
                            TT_Sec_Med,
                            TT_Sec_Med_F,
                            TT_Sec_SS_Med,
                            TT_Sec_SS_Med_F,
                            TT_Sec_SSHG_Med,
                            TT_Sec_SSHG_Med_F,
                            TT_Sec_Cnt,
                            TT_Sec_Cnt_F,
                            TT_Sec_SS_Cnt,
                            TT_Sec_SS_Cnt_F,
                            TT_Sec_SSHG_Cnt,
                            TT_Sec_SSHG_Cnt_F,
                            TravelTime_Hr,
                            TT_Hr_q2,
                            TT_Hr_q98,
                            TT_Hr_SS_q5,
                            TT_Hr_SS_q95,
                            TT_Hr_SSHG_q5,
                            TT_Hr_SSHG_q95,
                            TT_Hr_Mean,
                            TT_Hr_Mean_F,
                            TT_Hr_SS_Mean,
                            TT_Hr_SS_Mean_F,
                            TT_Hr_SSHG_Mean,
                            TT_Hr_SSHG_Mean_F,
                            TT_Hr_Med,
                            TT_Hr_Med_F,
                            TT_Hr_SS_Med,
                            TT_Hr_SS_Med_F,
                            TT_Hr_SSHG_Med,
                            TT_Hr_SSHG_Med_F,
                            TT_Hr_Cnt,
                            TT_Hr_Cnt_F,
                            TT_Hr_SS_Cnt,
                            TT_Hr_SS_Cnt_F,
                            TT_Hr_SSHG_Cnt,
                            TT_Hr_SSHG_Cnt_F,
                            SpeedAvg_Mph
                           )
rm(AllDays_DirChange)
str(AllDays_NewOrder)
'data.frame':   2809529 obs. of  114 variables:
 $ RowNum_OG             : int  1 3 4 5 6 7 9 10 11 12 ...
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID          : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2            : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2            : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID              : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc            : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean          : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc             : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type            : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min        : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time            : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2           : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time            : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance     : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1: int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi  : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft     : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi     : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs: num  NA 0.15 0.105 0.165 0.832 ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5           : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95          : num  NA 0.626 0.242 1.008 0.176 ...
 $ TD_Mi_SSHG_q5         : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95        : num  NA 0.627 0.242 0.7 0.182 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean         : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F       : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SSHG_Mean       : num  NaN 0.442 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Mean_F     : num  NaN 0.491 0.242 0.7 0.182 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med          : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F        : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SSHG_Med        : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Med_F      : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt          : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F        : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TD_Mi_SSHG_Cnt        : int  0 7 1 1 1 23 6 29 28 3 ...
 $ TD_Mi_SSHG_Cnt_F      : int  0 5 1 1 1 19 4 25 24 1 ...
 $ TravelTime_Sec        : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5          : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95         : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Sec_SSHG_q5        : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95       : num  NA 276 37 25 190 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean        : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F      : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SSHG_Mean      : num  NaN 202 37 25 190 ...
 $ TT_Sec_SSHG_Mean_F    : num  NaN 226 37 25 190 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med         : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F       : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SSHG_Med       : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_SSHG_Med_F     : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt         : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F       : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Sec_SSHG_Cnt       : int  0 7 1 1 1 35 6 36 35 3 ...
 $ TT_Sec_SSHG_Cnt_F     : int  0 5 1 1 1 31 4 32 32 1 ...
 $ TravelTime_Hr         : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5           : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95          : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TT_Hr_SSHG_q5         : num  NA 0.01656 0.01028 0.00694 0.05278 ...
 $ TT_Hr_SSHG_q95        : num  NA 0.07653 0.01028 0.00694 0.05278 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_SS_Mean         : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F       : num  NaN 0.0608 0.0103 0.0182 NaN ...
  [list output truncated]
# View(head(AllDays_NewOrder, 500))
# View(tail(AllDays_NewOrder, 500))

Summarizing the data to help spot anomolies.

summary(AllDays_NewOrder)
   RowNum_OG       group      StartStop_ID       BusDay_EventNum      Bus_ID    
 Min.   :      1   1:559521   Length:2809529     Min.   :   1.0   Min.   :  11  
 1st Qu.: 784722   2:561389   Class :character   1st Qu.: 113.0   1st Qu.:2922  
 Median :1563300   3:567794   Mode  :character   Median : 248.0   Median :6195  
 Mean   :1562504   4:559180                      Mean   : 290.5   Mean   :5382  
 3rd Qu.:2337981   5:561645                      3rd Qu.: 428.0   3rd Qu.:7104  
 Max.   :3119443                                 Max.   :1344.0   Max.   :8105  
                                                                                
    Route            RteChange2         RouteAlt        DirChange2     
 Length:2809529     Change:  23772   2      :1128810   Change:  65126  
 Class :character   Same  :2785757   1      :1065425   Same  :2744403  
 Mode  :character                    3      : 260372                   
                                     4      : 130801                   
                                     5      :  75039                   
                                     6      :  56408                   
                                     (Other):  92674                   
 Route_Direction   Stop_Sequence      Start_ID          Start_Desc       
 SOUTH   :739235   Min.   :  1.00   Length:2809529     Length:2809529    
 NORTH   :735203   1st Qu.: 12.00   Class :character   Class :character  
 WEST    :649706   Median : 24.00   Mode  :character   Mode  :character  
 EAST    :628074   Mean   : 26.83                                        
 LOOP    : 35611   3rd Qu.: 39.00                                        
 CLOCKWIS: 10671   Max.   :104.00                                        
 (Other) : 11029                                                         
 StopID_Clean       StopID_Indicator  Stop_Desc           Event_Type 
 Length:2809529     ID_Bad:  18948   Length:2809529     Min.   :3.0  
 Class :character   ID_OK :2790581   Class :character   1st Qu.:3.0  
 Mode  :character                    Mode  :character   Median :4.0  
                                                        Mean   :3.6  
                                                        3rd Qu.:4.0  
                                                        Max.   :5.0  
                                                                     
                                          Event_Description   Event_Time_Yr 
 Serviced Stop                                     :1127366   Min.   :2016  
 Unknown Stop                                      :   2579   1st Qu.:2016  
 UnServiced Stop                                   :1679584   Median :2016  
                                                              Mean   :2016  
                                                              3rd Qu.:2016  
                                                              Max.   :2016  
                                                                            
 Event_Time_Mth Event_Time_Date Event_Time_Day Event_Time_Hr    Event_Time_HrGroup
 Min.   :10     Min.   :3.000   Sun  :     0   Min.   : 0.00   Group6_8  :611612  
 1st Qu.:10     1st Qu.:4.000   Mon  :559521   1st Qu.: 8.00   Group15_17:560103  
 Median :10     Median :5.000   Tues :561389   Median :13.00   Group18_20:461056  
 Mean   :10     Mean   :5.001   Wed  :567794   Mean   :12.97   Group9_11 :396514  
 3rd Qu.:10     3rd Qu.:6.000   Thurs:559180   3rd Qu.:18.00   Group12_14:353603  
 Max.   :10     Max.   :7.000   Fri  :561645   Max.   :23.00   Group21_23:244522  
                                Sat  :     0                   (Other)   :182119  
 Event_Time_Min    Event_Time                  Departure_Time               
 Min.   : 0.00   Min.   :2016-10-03 00:00:00   Min.   :2016-10-03 00:00:00  
 1st Qu.:14.00   1st Qu.:2016-10-04 08:36:14   1st Qu.:2016-10-04 08:36:20  
 Median :29.00   Median :2016-10-05 13:49:29   Median :2016-10-05 13:49:38  
 Mean   :29.43   Mean   :2016-10-05 13:29:21   Mean   :2016-10-05 13:29:28  
 3rd Qu.:44.00   3rd Qu.:2016-10-06 17:58:06   3rd Qu.:2016-10-06 17:58:13  
 Max.   :59.00   Max.   :2016-10-07 23:59:59   Max.   :2016-10-08 00:12:31  
                                                                            
   Dwell_Time       Dwell_Time2         Delta_Time         Latitude    
 Min.   :   0.00   Min.   :   0.000   Min.   :-5606.0   Min.   : 0.00  
 1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   14.0   1st Qu.:38.86  
 Median :   0.00   Median :   0.000   Median :  157.0   Median :38.90  
 Mean   :  12.56   Mean   :   6.359   Mean   :  268.8   Mean   :38.91  
 3rd Qu.:   5.00   3rd Qu.:   4.000   3rd Qu.:  396.0   3rd Qu.:38.96  
 Max.   :6205.00   Max.   :6205.000   Max.   : 9426.0   Max.   :39.19  
                                                                       
   Longitude         Heading      Odometer_Distance  Odometer_Distance_Lag1
 Min.   :-77.45   Min.   :  0.0   Min.   :       0   Min.   :       0      
 1st Qu.:-77.07   1st Qu.: 89.0   1st Qu.:  177595   1st Qu.:  177326      
 Median :-77.02   Median :180.0   Median :  377510   Median :  376934      
 Mean   :-77.02   Mean   :176.9   Mean   :  426254   Mean   :  425713      
 3rd Qu.:-76.97   3rd Qu.:269.0   3rd Qu.:  623667   3rd Qu.:  622879      
 Max.   :  0.00   Max.   :360.0   Max.   :11108034   Max.   :10853226      
                                                     NA's   :6528          
 Odometer_Distance_Mi TravelDistance_Ft TravelDistance_Mi TravelDistance_Mi_Hvrs
 Min.   :   0.00      Min.   :      1   Min.   :  0.0     Min.   : 0.000        
 1st Qu.:  33.64      1st Qu.:    699   1st Qu.:  0.1     1st Qu.: 0.106        
 Median :  71.50      Median :   1044   Median :  0.2     Median : 0.142        
 Mean   :  80.73      Mean   :   1624   Mean   :  0.3     Mean   : 0.201        
 3rd Qu.: 118.12      3rd Qu.:   1518   3rd Qu.:  0.3     3rd Qu.: 0.193        
 Max.   :2103.79      Max.   :1323464   Max.   :250.7     Max.   :24.407        
                      NA's   :322734    NA's   :322734    NA's   :6528          
    TD_Mi_q2         TD_Mi_q98       TD_Mi_SS_q5       TD_Mi_SS_q95    
 Min.   :0.05208   Min.   :0.9585   Min.   :  0.000   Min.   :  0.000  
 1st Qu.:0.05208   1st Qu.:0.9585   1st Qu.:  0.086   1st Qu.:  0.262  
 Median :0.05208   Median :0.9585   Median :  0.104   Median :  0.326  
 Mean   :0.05208   Mean   :0.9585   Mean   :  0.164   Mean   :  0.488  
 3rd Qu.:0.05208   3rd Qu.:0.9585   3rd Qu.:  0.139   3rd Qu.:  0.436  
 Max.   :0.05208   Max.   :0.9585   Max.   :219.163   Max.   :246.949  
                                    NA's   :24757     NA's   :24757    
 TD_Mi_SSHG_q5    TD_Mi_SSHG_q95     TD_Mi_Mean      TD_Mi_Mean_F   
 Min.   :  0.00   Min.   :  0.00   Min.   :0.3076   Min.   :0.2318  
 1st Qu.:  0.09   1st Qu.:  0.25   1st Qu.:0.3076   1st Qu.:0.2318  
 Median :  0.11   Median :  0.31   Median :0.3076   Median :0.2318  
 Mean   :  0.18   Mean   :  0.47   Mean   :0.3076   Mean   :0.2318  
 3rd Qu.:  0.15   3rd Qu.:  0.42   3rd Qu.:0.3076   3rd Qu.:0.2318  
 Max.   :250.66   Max.   :250.66   Max.   :0.3076   Max.   :0.2318  
 NA's   :35629    NA's   :35629                                     
 TD_Mi_SS_Mean     TD_Mi_SS_Mean_F   TD_Mi_SSHG_Mean  TD_Mi_SSHG_Mean_F
 Min.   :  0.000   Min.   :  0.000   Min.   :  0.00   Min.   :  0.00   
 1st Qu.:  0.172   1st Qu.:  0.166   1st Qu.:  0.17   1st Qu.:  0.16   
 Median :  0.212   Median :  0.207   Median :  0.21   Median :  0.21   
 Mean   :  0.307   Mean   :  0.291   Mean   :  0.31   Mean   :  0.29   
 3rd Qu.:  0.267   3rd Qu.:  0.260   3rd Qu.:  0.27   3rd Qu.:  0.26   
 Max.   :219.163   Max.   :219.163   Max.   :250.66   Max.   :250.66   
 NA's   :24757     NA's   :27919     NA's   :35629    NA's   :44458    
   TD_Mi_Med       TD_Mi_Med_F      TD_Mi_SS_Med     TD_Mi_SS_Med_F   
 Min.   :0.1977   Min.   :0.1977   Min.   :  0.000   Min.   :  0.000  
 1st Qu.:0.1977   1st Qu.:0.1977   1st Qu.:  0.146   1st Qu.:  0.146  
 Median :0.1977   Median :0.1977   Median :  0.196   Median :  0.196  
 Mean   :0.1977   Mean   :0.1977   Mean   :  0.288   Mean   :  0.282  
 3rd Qu.:0.1977   3rd Qu.:0.1977   3rd Qu.:  0.265   3rd Qu.:  0.265  
 Max.   :0.1977   Max.   :0.1977   Max.   :219.163   Max.   :219.163  
                                   NA's   :24757     NA's   :27919    
 TD_Mi_SSHG_Med   TD_Mi_SSHG_Med_F   TD_Mi_Cnt        TD_Mi_Cnt_F     
 Min.   :  0.00   Min.   :  0.00   Min.   :2486795   Min.   :2387406  
 1st Qu.:  0.14   1st Qu.:  0.14   1st Qu.:2486795   1st Qu.:2387406  
 Median :  0.20   Median :  0.20   Median :2486795   Median :2387406  
 Mean   :  0.29   Mean   :  0.28   Mean   :2486795   Mean   :2387406  
 3rd Qu.:  0.27   3rd Qu.:  0.27   3rd Qu.:2486795   3rd Qu.:2387406  
 Max.   :250.66   Max.   :250.66   Max.   :2486795   Max.   :2387406  
 NA's   :35629    NA's   :44458                                       
  TD_Mi_SS_Cnt    TD_Mi_SS_Cnt_F   TD_Mi_SSHG_Cnt   TD_Mi_SSHG_Cnt_F
 Min.   :   0.0   Min.   :   0.0   Min.   :  0.00   Min.   :  0.00  
 1st Qu.: 163.0   1st Qu.: 146.0   1st Qu.: 26.00   1st Qu.: 22.00  
 Median : 280.0   Median : 252.0   Median : 45.00   Median : 39.00  
 Mean   : 347.4   Mean   : 312.7   Mean   : 57.27   Mean   : 50.85  
 3rd Qu.: 456.0   3rd Qu.: 411.0   3rd Qu.: 75.00   3rd Qu.: 67.00  
 Max.   :1543.0   Max.   :1388.0   Max.   :663.00   Max.   :595.00  
                                                                    
 TravelTime_Sec      TT_Sec_q2    TT_Sec_q98   TT_Sec_SS_q5      TT_Sec_SS_q95     
 Min.   :    1.0   Min.   :10   Min.   :349   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   25.0   1st Qu.:10   1st Qu.:349   1st Qu.:   15.00   1st Qu.:   48.00  
 Median :   39.0   Median :10   Median :349   Median :   22.00   Median :   80.05  
 Mean   :  104.9   Mean   :10   Mean   :349   Mean   :   61.26   Mean   :  183.28  
 3rd Qu.:   72.0   3rd Qu.:10   3rd Qu.:349   3rd Qu.:   34.00   3rd Qu.:  134.60  
 Max.   :60750.0   Max.   :10   Max.   :349   Max.   :60750.00   Max.   :60750.00  
 NA's   :6641                                 NA's   :6531       NA's   :6531      
 TT_Sec_SSHG_q5     TT_Sec_SSHG_q95     TT_Sec_Mean    TT_Sec_Mean_F  
 Min.   :    1.00   Min.   :    1.00   Min.   :104.9   Min.   :56.61  
 1st Qu.:   16.00   1st Qu.:   43.80   1st Qu.:104.9   1st Qu.:56.61  
 Median :   23.40   Median :   72.95   Median :104.9   Median :56.61  
 Mean   :   67.33   Mean   :  169.21   Mean   :104.9   Mean   :56.61  
 3rd Qu.:   36.70   3rd Qu.:  123.65   3rd Qu.:104.9   3rd Qu.:56.61  
 Max.   :60750.00   Max.   :60750.00   Max.   :104.9   Max.   :56.61  
 NA's   :6535       NA's   :6535                                      
 TT_Sec_SS_Mean     TT_Sec_SS_Mean_F   TT_Sec_SSHG_Mean   TT_Sec_SSHG_Mean_F
 Min.   :    1.00   Min.   :    1.00   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   29.06   1st Qu.:   27.54   1st Qu.:   28.38   1st Qu.:   27.21  
 Median :   44.16   Median :   41.91   Median :   43.38   Median :   41.48  
 Mean   :  104.88   Mean   :   91.34   Mean   :  104.88   Mean   :   93.53  
 3rd Qu.:   73.30   3rd Qu.:   69.25   3rd Qu.:   72.93   3rd Qu.:   70.12  
 Max.   :60750.00   Max.   :60750.00   Max.   :60750.00   Max.   :60750.00  
 NA's   :6531       NA's   :10519      NA's   :6535       NA's   :12811     
   TT_Sec_Med  TT_Sec_Med_F TT_Sec_SS_Med      TT_Sec_SS_Med_F   
 Min.   :39   Min.   :39    Min.   :    1.00   Min.   :    1.00  
 1st Qu.:39   1st Qu.:39    1st Qu.:   26.00   1st Qu.:   26.00  
 Median :39   Median :39    Median :   39.00   Median :   39.00  
 Mean   :39   Mean   :39    Mean   :   91.55   Mean   :   84.82  
 3rd Qu.:39   3rd Qu.:39    3rd Qu.:   65.00   3rd Qu.:   65.00  
 Max.   :39   Max.   :39    Max.   :60750.00   Max.   :60750.00  
                            NA's   :6531       NA's   :10519     
 TT_Sec_SSHG_Med    TT_Sec_SSHG_Med_F    TT_Sec_Cnt       TT_Sec_Cnt_F    
 Min.   :    1.00   Min.   :    1.00   Min.   :2802888   Min.   :2705189  
 1st Qu.:   26.00   1st Qu.:   26.00   1st Qu.:2802888   1st Qu.:2705189  
 Median :   39.00   Median :   38.50   Median :2802888   Median :2705189  
 Mean   :   94.94   Mean   :   88.44   Mean   :2802888   Mean   :2705189  
 3rd Qu.:   67.00   3rd Qu.:   66.50   3rd Qu.:2802888   3rd Qu.:2705189  
 Max.   :60750.00   Max.   :60750.00   Max.   :2802888   Max.   :2705189  
 NA's   :6535       NA's   :12811                                         
 TT_Sec_SS_Cnt    TT_Sec_SS_Cnt_F  TT_Sec_SSHG_Cnt  TT_Sec_SSHG_Cnt_F
 Min.   :   0.0   Min.   :   0.0   Min.   :  0.00   Min.   :  0.00   
 1st Qu.: 194.0   1st Qu.: 177.0   1st Qu.: 29.00   1st Qu.: 26.00   
 Median : 310.0   Median : 282.0   Median : 51.00   Median : 46.00   
 Mean   : 384.4   Mean   : 349.8   Mean   : 63.46   Mean   : 57.09   
 3rd Qu.: 497.0   3rd Qu.: 452.0   3rd Qu.: 83.00   3rd Qu.: 74.00   
 Max.   :1664.0   Max.   :1523.0   Max.   :691.00   Max.   :634.00   
                                                                     
 TravelTime_Hr       TT_Hr_q2          TT_Hr_q98        TT_Hr_SS_q5    
 Min.   : 0.000   Min.   :0.002778   Min.   :0.09694   Min.   : 0.000  
 1st Qu.: 0.007   1st Qu.:0.002778   1st Qu.:0.09694   1st Qu.: 0.004  
 Median : 0.011   Median :0.002778   Median :0.09694   Median : 0.006  
 Mean   : 0.029   Mean   :0.002778   Mean   :0.09694   Mean   : 0.017  
 3rd Qu.: 0.020   3rd Qu.:0.002778   3rd Qu.:0.09694   3rd Qu.: 0.009  
 Max.   :16.875   Max.   :0.002778   Max.   :0.09694   Max.   :16.875  
 NA's   :6641                                          NA's   :6531    
  TT_Hr_SS_q95    TT_Hr_SSHG_q5    TT_Hr_SSHG_q95     TT_Hr_Mean     
 Min.   : 0.000   Min.   : 0.000   Min.   : 0.000   Min.   :0.02913  
 1st Qu.: 0.013   1st Qu.: 0.004   1st Qu.: 0.012   1st Qu.:0.02913  
 Median : 0.022   Median : 0.006   Median : 0.020   Median :0.02913  
 Mean   : 0.051   Mean   : 0.019   Mean   : 0.047   Mean   :0.02913  
 3rd Qu.: 0.037   3rd Qu.: 0.010   3rd Qu.: 0.034   3rd Qu.:0.02913  
 Max.   :16.875   Max.   :16.875   Max.   :16.875   Max.   :0.02913  
 NA's   :6531     NA's   :6535     NA's   :6535                      
  TT_Hr_Mean_F     TT_Hr_SS_Mean    TT_Hr_SS_Mean_F  TT_Hr_SSHG_Mean 
 Min.   :0.01573   Min.   : 0.000   Min.   : 0.000   Min.   : 0.000  
 1st Qu.:0.01573   1st Qu.: 0.008   1st Qu.: 0.008   1st Qu.: 0.008  
 Median :0.01573   Median : 0.012   Median : 0.012   Median : 0.012  
 Mean   :0.01573   Mean   : 0.029   Mean   : 0.025   Mean   : 0.029  
 3rd Qu.:0.01573   3rd Qu.: 0.020   3rd Qu.: 0.019   3rd Qu.: 0.020  
 Max.   :0.01573   Max.   :16.875   Max.   :16.875   Max.   :16.875  
                   NA's   :6531     NA's   :10532    NA's   :6535    
 TT_Hr_SSHG_Mean_F   TT_Hr_Med        TT_Hr_Med_F       TT_Hr_SS_Med   
 Min.   : 0.000    Min.   :0.01083   Min.   :0.01083   Min.   : 0.000  
 1st Qu.: 0.008    1st Qu.:0.01083   1st Qu.:0.01083   1st Qu.: 0.007  
 Median : 0.012    Median :0.01083   Median :0.01083   Median : 0.011  
 Mean   : 0.026    Mean   :0.01083   Mean   :0.01083   Mean   : 0.025  
 3rd Qu.: 0.019    3rd Qu.:0.01083   3rd Qu.:0.01083   3rd Qu.: 0.018  
 Max.   :16.875    Max.   :0.01083   Max.   :0.01083   Max.   :16.875  
 NA's   :12895                                         NA's   :6531    
 TT_Hr_SS_Med_F   TT_Hr_SSHG_Med   TT_Hr_SSHG_Med_F   TT_Hr_Cnt      
 Min.   : 0.000   Min.   : 0.000   Min.   : 0.000   Min.   :2802888  
 1st Qu.: 0.007   1st Qu.: 0.007   1st Qu.: 0.007   1st Qu.:2802888  
 Median : 0.011   Median : 0.011   Median : 0.011   Median :2802888  
 Mean   : 0.024   Mean   : 0.026   Mean   : 0.025   Mean   :2802888  
 3rd Qu.: 0.018   3rd Qu.: 0.019   3rd Qu.: 0.018   3rd Qu.:2802888  
 Max.   :16.875   Max.   :16.875   Max.   :16.875   Max.   :2802888  
 NA's   :10532    NA's   :6535     NA's   :12895                     
  TT_Hr_Cnt_F       TT_Hr_SS_Cnt    TT_Hr_SS_Cnt_F   TT_Hr_SSHG_Cnt  
 Min.   :2705189   Min.   :   0.0   Min.   :   0.0   Min.   :  0.00  
 1st Qu.:2705189   1st Qu.: 194.0   1st Qu.: 176.0   1st Qu.: 29.00  
 Median :2705189   Median : 310.0   Median : 282.0   Median : 51.00  
 Mean   :2705189   Mean   : 384.4   Mean   : 349.6   Mean   : 63.46  
 3rd Qu.:2705189   3rd Qu.: 497.0   3rd Qu.: 452.0   3rd Qu.: 83.00  
 Max.   :2705189   Max.   :1664.0   Max.   :1523.0   Max.   :691.00  
                                                                     
 TT_Hr_SSHG_Cnt_F  SpeedAvg_Mph    
 Min.   :  0.00   Min.   :    0.0  
 1st Qu.: 26.00   1st Qu.:   10.1  
 Median : 46.00   Median :   16.7  
 Mean   : 57.05   Mean   :   26.5  
 3rd Qu.: 74.00   3rd Qu.:   31.2  
 Max.   :634.00   Max.   :22924.1  
                  NA's   :322762   

Investigation of TravelDistance_Mi.

View(TravDistMi_Pctiles): 99% of TravelDistance_Mi are about 1 mile or less…but some weird TravelDistance_Mi values (e.g., 584 miles traveled) exist.

TravDistMi_Ntile <- as.data.frame(AllDays_NewOrder$TravelDistance_Mi) %>% 
  mutate(#Pctile = ntile(AllDays_NewOrder$TravelDistance_Mi, 100),
         #MinR = min_rank(AllDays_NewOrder$TravelDistance_Mi),
         PctR = percent_rank(AllDays_NewOrder$TravelDistance_Mi),
         PctR_Round = round(PctR, 2)
        ) 
colnames(TravDistMi_Ntile)[1] <- "TravelDistance_Mi"
# str(TravDistMi_Ntile)
TravDistMi_Ntile_Rows <- nrow(TravDistMi_Ntile)
# View(tail(TravDistMi_Ntile, 500))
TravDistMi_Pctiles <- group_by(TravDistMi_Ntile,
                               PctR_Round
                              ) %>% 
  summarise(
    MinTravDistMiAtPctile = min(TravelDistance_Mi),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / TravDistMi_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )
rm(TravDistMi_Ntile)
rm(TravDistMi_Ntile_Rows)
View(TravDistMi_Pctiles)
TravDistMi_Pctiles

Investigation of TravelDistance_Mi.

Why are some TravelDistance_Mi “NA”? It looks like partially because the records are the first trip of the day (for that bus), so I purposefully set the distance to “NA”. Another reason is due to the odometer recording a value less than the previous odometer recording. In most cases, I have no explanation for this - though I have observed about 67% of all instances where TravelDistance_Mi is NA (other than because it’s the first record of the day) are instances where DirChange2 is “Change”. This is weird and should be asked to WMATA.

# View(head(AllDays_NewOrder, 500))
View(filter(AllDays_NewOrder,
            BusDay_EventNum != 1 # When BusDay_EventNum == 1, TravelDistance_Mi is NA by design (don't want to calculate distance based on yesterday's position)
           ) %>% 
       group_by(StartStop_ID) %>% 
       summarise(Cnts = sum(is.na(TravelDistance_Mi)
                           )
                ) %>% 
       arrange(desc(Cnts)
              )
    )
View(filter(AllDays_NewOrder,
            StartStop_ID == "1000245--1000211"
           ) %>% 
       select(RowNum_OG,
              StartStop_ID,
              Event_Time,
              Event_Time_HrGroup,
              Bus_ID,
              TravelDistance_Mi,
              TravelDistance_Mi_Hvrs,
              TD_Mi_SS_Mean,
              TD_Mi_SS_Mean_F,
              TD_Mi_SSHG_Mean,
              TD_Mi_SSHG_Mean_F,
              TD_Mi_SS_Med,
              TD_Mi_SS_Med_F,
              TD_Mi_SSHG_Med,
              TD_Mi_SSHG_Med_F,
              TD_Mi_SS_Cnt,
              TD_Mi_SS_Cnt_F,
              TD_Mi_SSHG_Cnt,
              TD_Mi_SSHG_Cnt_F
              ) %>% 
       mutate(Ratio_MeanToHvrs = TD_Mi_SS_Mean / TravelDistance_Mi_Hvrs) %>% 
       arrange(Event_Time)
    )
View(filter(AllDays_NewOrder,
            is.na(TravelDistance_Mi)
           )
    )
# These records are NA becuase the record is the first record of the day (the Event_Time_Date)
View(filter(AllDays_NewOrder,
            between(RowNum_OG, 326, 346) | # 336
              between(RowNum_OG, 591, 611) | # 601
              between(RowNum_OG, 845, 865) # 855
           )
    )

Investigation of TravelDistance_Mi.

These records are NA becuase the current record odometer is less than the previous record odometer. Theoretically, this should NOT happen. Me: it appears that about 67% of all instances where TravelDistance_Mi is NA (other than because it’s th first record of the day) are instances where DirChange2 is “Change”. This is weird and should be asked to WMATA.

View(filter(AllDays_NewOrder,
            between(RowNum_OG, 194, 214) | # 204
              between(RowNum_OG, 440, 460) | # 450
              between(RowNum_OG, 478, 498) | # 488
              between(RowNum_OG, 510, 530) # 520
           )
    )
TestTable <- filter(AllDays_NewOrder,
                    BusDay_EventNum != 1
                   ) %>% 
  mutate(TravelDistance_NA = as.factor(ifelse(is.na(TravelDistance_Mi),
                                              "True",
                                              "False"
                                             )
                                      )
        ) %>%
  group_by(DirChange2, TravelDistance_NA) %>%
  summarise(TravDistMi_NACnts = n()
           )
# TestTable
TestTable_Spread <- as.data.frame(spread(TestTable,
                                         TravelDistance_NA,
                                         TravDistMi_NACnts
                                        )
                                 ) %>% 
  select(False,
         True
        )
row.names(TestTable_Spread) <- c("Change", "Same")
# str(TestTable_Spread)
# TestTable_Spread
prop.table(as.table(as.matrix(TestTable_Spread)
                   ),
           1
          )
           False      True
Change 0.8267006 0.1732994
Same   0.8884818 0.1115182
prop.table(as.table(as.matrix(TestTable_Spread)
                   ),
           2
          )
            False       True
Change 0.01948009 0.03211514
Same   0.98051991 0.96788486

Investigation of TravelDistance_Mi.

Let’s look at just the TravelDistance_Mi values that are NOT “NA”.

rm(TestTable)
rm(TestTable_Spread)
TravelDistance_Mi_NoNA <- filter(AllDays_NewOrder,
                                 # TravelDistance_Mi != 0 &
                                 !is.na(TravelDistance_Mi)
                                )
dim(AllDays_NewOrder)
[1] 2809529     114
dim(TravelDistance_Mi_NoNA)
[1] 2486795     114
nrow(AllDays_NewOrder) - nrow(TravelDistance_Mi_NoNA)
[1] 322734
str(TravelDistance_Mi_NoNA)
'data.frame':   2486795 obs. of  114 variables:
 $ RowNum_OG             : int  3 4 5 6 7 9 10 11 12 13 ...
 $ group                 : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID          : chr  "5004572--5004573" "5004573--5002210" "5002210--5002209" "5002209--5000070" ...
 $ BusDay_EventNum       : int  2 3 4 5 6 7 8 9 10 11 ...
 $ Bus_ID                : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                 : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2            : Factor w/ 2 levels "Change","Same": 2 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt              : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 6 6 6 6 6 ...
 $ DirChange2            : Factor w/ 2 levels "Change","Same": 2 2 2 2 2 1 2 2 2 2 ...
 $ Route_Direction       : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence         : int  6 3 2 8 1 2 3 4 2 6 ...
 $ Start_ID              : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ Start_Desc            : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ StopID_Clean          : chr  "5004573" "5002210" "5002209" "5000070" ...
 $ StopID_Indicator      : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc             : chr  "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" "FRANCONIA-SPRGFLD STA. + BUS BAY D" ...
 $ Event_Type            : int  4 4 4 3 3 4 4 4 4 4 ...
 $ Event_Description     : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 1 1 3 3 3 3 3 ...
 $ Event_Time_Yr         : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth        : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date       : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day        : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr         : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup    : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min        : int  9 10 10 13 14 21 21 23 23 26 ...
 $ Event_Time            : POSIXct, format: "2016-10-03 06:09:47" "2016-10-03 06:10:24" ...
 $ Departure_Time        : POSIXct, format: "2016-10-03 06:09:47" "2016-10-03 06:10:24" ...
 $ Dwell_Time            : int  0 0 0 0 104 0 0 0 0 0 ...
 $ Dwell_Time2           : num  0 0 0 0 104 0 0 0 0 0 ...
 $ Delta_Time            : int  24 165 25 73 719 74 76 63 69 165 ...
 $ Latitude              : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude             : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading               : int  97 276 15 119 100 274 104 241 274 1 ...
 $ Odometer_Distance     : int  45139 46418 50115 51074 51303 55633 56163 56285 57262 58363 ...
 $ Odometer_Distance_Lag1: int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Mi  : num  8.55 8.79 9.49 9.67 9.72 ...
 $ TravelDistance_Ft     : int  1596 1279 3697 959 229 4330 530 122 977 1101 ...
 $ TravelDistance_Mi     : num  0.3023 0.2422 0.7002 0.1816 0.0434 ...
 $ TravelDistance_Mi_Hvrs: num  0.15 0.105 0.165 0.832 0.068 ...
 $ TD_Mi_q2              : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98             : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5           : num  0.025246 0.242235 0.732434 0.079432 0.000436 ...
 $ TD_Mi_SS_q95          : num  0.626 0.242 1.008 0.176 10.435 ...
 $ TD_Mi_SSHG_q5         : num  0.09956 0.24223 0.70019 0.18163 0.00269 ...
 $ TD_Mi_SSHG_q95        : num  0.627 0.242 0.7 0.182 0.497 ...
 $ TD_Mi_Mean            : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F          : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean         : num  0.437 0.242 0.908 0.128 1.166 ...
 $ TD_Mi_SS_Mean_F       : num  0.457 0.242 0.977 NaN 0.226 ...
 $ TD_Mi_SSHG_Mean       : num  0.442 0.242 0.7 0.182 0.232 ...
 $ TD_Mi_SSHG_Mean_F     : num  0.491 0.242 0.7 0.182 0.228 ...
 $ TD_Mi_Med             : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F           : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med          : num  0.5116 0.2422 0.9616 0.1278 0.0426 ...
 $ TD_Mi_SS_Med_F        : num  0.5116 0.2422 1.0081 NA 0.0426 ...
 $ TD_Mi_SSHG_Med        : num  0.512 0.242 0.7 0.182 0.108 ...
 $ TD_Mi_SSHG_Med_F      : num  0.512 0.242 0.7 0.182 0.108 ...
 $ TD_Mi_Cnt             : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F           : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt          : int  14 1 4 2 87 22 118 91 11 2 ...
 $ TD_Mi_SS_Cnt_F        : int  12 1 3 0 77 18 106 81 9 0 ...
 $ TD_Mi_SSHG_Cnt        : int  7 1 1 1 23 6 29 28 3 1 ...
 $ TD_Mi_SSHG_Cnt_F      : int  5 1 1 1 19 4 25 24 1 1 ...
 $ TravelTime_Sec        : num  180 37 25 190 29 288 52 76 8 189 ...
 $ TT_Sec_q2             : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98            : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5          : num  11.9 37 30.5 172.9 10 ...
 $ TT_Sec_SS_q95         : num  346.3 37 75.8 189.1 1737.2 ...
 $ TT_Sec_SSHG_q5        : num  59.6 37 25 190 11.6 236 51.5 55 8.8 189 ...
 $ TT_Sec_SSHG_q95       : num  276 37 25 190 675 ...
 $ TT_Sec_Mean           : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F         : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean        : num  215.8 37 58.2 181 585.3 ...
 $ TT_Sec_SS_Mean_F      : num  218.9 37 65.5 NaN 249.3 ...
 $ TT_Sec_SSHG_Mean      : num  202 37 25 190 257 ...
 $ TT_Sec_SSHG_Mean_F    : num  226 37 25 190 244 ...
 $ TT_Sec_Med            : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F          : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med         : num  223.5 37 65.5 181 33 ...
 $ TT_Sec_SS_Med_F       : num  223.5 37 65.5 NA 32 ...
 $ TT_Sec_SSHG_Med       : num  219 37 25 190 134 286 60 65 16 189 ...
 $ TT_Sec_SSHG_Med_F     : num  219 37 25 190 134 286 60 65 16 189 ...
 $ TT_Sec_Cnt            : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F          : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt         : int  14 1 4 2 173 22 141 141 11 2 ...
 $ TT_Sec_SS_Cnt_F       : int  12 1 2 0 156 18 127 128 9 0 ...
 $ TT_Sec_SSHG_Cnt       : int  7 1 1 1 35 6 36 35 3 1 ...
 $ TT_Sec_SSHG_Cnt_F     : int  5 1 1 1 31 4 32 32 1 1 ...
 $ TravelTime_Hr         : num  0.05 0.01028 0.00694 0.05278 0.00806 ...
 $ TT_Hr_q2              : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98             : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5           : num  0.00331 0.01028 0.00849 0.04803 0.00278 ...
 $ TT_Hr_SS_q95          : num  0.0962 0.0103 0.0211 0.0525 0.4826 ...
 $ TT_Hr_SSHG_q5         : num  0.01656 0.01028 0.00694 0.05278 0.00322 ...
 $ TT_Hr_SSHG_q95        : num  0.07653 0.01028 0.00694 0.05278 0.18739 ...
 $ TT_Hr_Mean            : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F          : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_SS_Mean         : num  0.0599 0.0103 0.0162 0.0503 0.1626 ...
 $ TT_Hr_SS_Mean_F       : num  0.0608 0.0103 0.0182 NaN 0.0692 ...
  [list output truncated]
summary(TravelDistance_Mi_NoNA)
   RowNum_OG       group      StartStop_ID       BusDay_EventNum      Bus_ID    
 Min.   :      3   1:496190   Length:2486795     Min.   :   2.0   Min.   :  11  
 1st Qu.: 786568   2:497932   Class :character   1st Qu.: 115.0   1st Qu.:2923  
 Median :1590497   3:501611   Mode  :character   Median : 251.0   Median :6202  
 Mean   :1578192   4:495069                      Mean   : 293.2   Mean   :5431  
 3rd Qu.:2351264   5:495993                      3rd Qu.: 431.0   3rd Qu.:7113  
 Max.   :3119443                                 Max.   :1344.0   Max.   :8105  
                                                                                
    Route            RteChange2         RouteAlt       DirChange2     
 Length:2486795     Change:  13709   2      :994645   Change:  48443  
 Class :character   Same  :2473086   1      :943279   Same  :2438352  
 Mode  :character                    3      :229032                   
                                     4      :117090                   
                                     5      : 67811                   
                                     6      : 51391                   
                                     (Other): 83547                   
 Route_Direction   Stop_Sequence      Start_ID          Start_Desc       
 SOUTH   :667198   Min.   :  1.00   Length:2486795     Length:2486795    
 NORTH   :662471   1st Qu.: 12.00   Class :character   Class :character  
 WEST    :565616   Median : 24.00   Mode  :character   Mode  :character  
 EAST    :543386   Mean   : 27.13                                        
 LOOP    : 33484   3rd Qu.: 39.00                                        
 CLOCKWIS:  7012   Max.   :104.00                                        
 (Other) :  7628                                                         
 StopID_Clean       StopID_Indicator  Stop_Desc           Event_Type   
 Length:2486795     ID_Bad:  14271   Length:2486795     Min.   :3.000  
 Class :character   ID_OK :2472524   Class :character   1st Qu.:3.000  
 Mode  :character                    Mode  :character   Median :4.000  
                                                        Mean   :3.626  
                                                        3rd Qu.:4.000  
                                                        Max.   :5.000  
                                                                       
                                          Event_Description   Event_Time_Yr 
 Serviced Stop                                     : 930934   Min.   :2016  
 Unknown Stop                                      :   1794   1st Qu.:2016  
 UnServiced Stop                                   :1554067   Median :2016  
                                                              Mean   :2016  
                                                              3rd Qu.:2016  
                                                              Max.   :2016  
                                                                            
 Event_Time_Mth Event_Time_Date Event_Time_Day Event_Time_Hr    Event_Time_HrGroup
 Min.   :10     Min.   :3.000   Sun  :     0   Min.   : 0.00   Group6_8  :538348  
 1st Qu.:10     1st Qu.:4.000   Mon  :496190   1st Qu.: 8.00   Group15_17:497156  
 Median :10     Median :5.000   Tues :497932   Median :13.00   Group18_20:408957  
 Mean   :10     Mean   :4.999   Wed  :501611   Mean   :12.99   Group9_11 :351804  
 3rd Qu.:10     3rd Qu.:6.000   Thurs:495069   3rd Qu.:18.00   Group12_14:314050  
 Max.   :10     Max.   :7.000   Fri  :495993   Max.   :23.00   Group21_23:217259  
                                Sat  :     0                   (Other)   :159221  
 Event_Time_Min    Event_Time                  Departure_Time               
 Min.   : 0.00   Min.   :2016-10-03 00:00:09   Min.   :2016-10-03 00:00:09  
 1st Qu.:14.00   1st Qu.:2016-10-04 08:35:52   1st Qu.:2016-10-04 08:35:59  
 Median :29.00   Median :2016-10-05 13:46:00   Median :2016-10-05 13:46:06  
 Mean   :29.43   Mean   :2016-10-05 13:27:43   Mean   :2016-10-05 13:27:49  
 3rd Qu.:44.00   3rd Qu.:2016-10-06 17:57:32   3rd Qu.:2016-10-06 17:57:39  
 Max.   :59.00   Max.   :2016-10-07 23:59:59   Max.   :2016-10-08 00:12:31  
                                                                            
   Dwell_Time       Dwell_Time2         Delta_Time         Latitude    
 Min.   :   0.00   Min.   :   0.000   Min.   :-5606.0   Min.   : 0.00  
 1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   16.0   1st Qu.:38.86  
 Median :   0.00   Median :   0.000   Median :  160.0   Median :38.90  
 Mean   :  11.86   Mean   :   5.994   Mean   :  274.1   Mean   :38.91  
 3rd Qu.:   4.00   3rd Qu.:   4.000   3rd Qu.:  402.0   3rd Qu.:38.96  
 Max.   :6205.00   Max.   :6205.000   Max.   : 9426.0   Max.   :39.19  
                                                                       
   Longitude         Heading      Odometer_Distance  Odometer_Distance_Lag1
 Min.   :-77.45   Min.   :  0.0   Min.   :       1   Min.   :       0      
 1st Qu.:-77.07   1st Qu.: 89.0   1st Qu.:  200268   1st Qu.:  198635      
 Median :-77.01   Median :180.0   Median :  394700   Median :  393026      
 Mean   :-77.02   Mean   :176.7   Mean   :  443225   Mean   :  441601      
 3rd Qu.:-76.97   3rd Qu.:269.0   3rd Qu.:  633936   3rd Qu.:  632313      
 Max.   :  0.00   Max.   :360.0   Max.   :11108034   Max.   :10853226      
                                                                           
 Odometer_Distance_Mi TravelDistance_Ft TravelDistance_Mi   TravelDistance_Mi_Hvrs
 Min.   :   0.0002    Min.   :      1   Min.   :  0.00019   Min.   : 0.0000       
 1st Qu.:  37.9295    1st Qu.:    699   1st Qu.:  0.13239   1st Qu.: 0.1034       
 Median :  74.7538    Median :   1044   Median :  0.19773   Median : 0.1378       
 Mean   :  83.9442    Mean   :   1624   Mean   :  0.30760   Mean   : 0.1918       
 3rd Qu.: 120.0635    3rd Qu.:   1518   3rd Qu.:  0.28750   3rd Qu.: 0.1828       
 Max.   :2103.7943    Max.   :1323464   Max.   :250.65606   Max.   :24.1507       
                                                                                  
    TD_Mi_q2         TD_Mi_q98       TD_Mi_SS_q5         TD_Mi_SS_q95      
 Min.   :0.05208   Min.   :0.9585   Min.   :  0.00019   Min.   :  0.00019  
 1st Qu.:0.05208   1st Qu.:0.9585   1st Qu.:  0.08848   1st Qu.:  0.25878  
 Median :0.05208   Median :0.9585   Median :  0.10608   Median :  0.32239  
 Mean   :0.05208   Mean   :0.9585   Mean   :  0.16872   Mean   :  0.47949  
 3rd Qu.:0.05208   3rd Qu.:0.9585   3rd Qu.:  0.13977   3rd Qu.:  0.42822  
 Max.   :0.05208   Max.   :0.9585   Max.   :219.16288   Max.   :246.94938  
                                                                           
 TD_Mi_SSHG_q5       TD_Mi_SSHG_q95        TD_Mi_Mean      TD_Mi_Mean_F   
 Min.   :  0.00019   Min.   :  0.00019   Min.   :0.3076   Min.   :0.2318  
 1st Qu.:  0.09167   1st Qu.:  0.24754   1st Qu.:0.3076   1st Qu.:0.2318  
 Median :  0.11395   Median :  0.31174   Median :0.3076   Median :0.2318  
 Mean   :  0.18528   Mean   :  0.46625   Mean   :0.3076   Mean   :0.2318  
 3rd Qu.:  0.15093   3rd Qu.:  0.41899   3rd Qu.:0.3076   3rd Qu.:0.2318  
 Max.   :250.65606   Max.   :250.65606   Max.   :0.3076   Max.   :0.2318  
                                                                          
 TD_Mi_SS_Mean       TD_Mi_SS_Mean_F    TD_Mi_SSHG_Mean     TD_Mi_SSHG_Mean_F
 Min.   :  0.00019   Min.   :  0.0002   Min.   :  0.00019   Min.   :  0.000  
 1st Qu.:  0.17129   1st Qu.:  0.1663   1st Qu.:  0.16760   1st Qu.:  0.163  
 Median :  0.21082   Median :  0.2058   Median :  0.20965   Median :  0.206  
 Mean   :  0.30760   Mean   :  0.2916   Mean   :  0.30760   Mean   :  0.294  
 3rd Qu.:  0.26422   3rd Qu.:  0.2582   3rd Qu.:  0.26616   3rd Qu.:  0.262  
 Max.   :219.16288   Max.   :219.1629   Max.   :250.65606   Max.   :250.656  
                     NA's   :2678                           NA's   :4904     
   TD_Mi_Med       TD_Mi_Med_F      TD_Mi_SS_Med       TD_Mi_SS_Med_F    
 Min.   :0.1977   Min.   :0.1977   Min.   :  0.00019   Min.   :  0.0002  
 1st Qu.:0.1977   1st Qu.:0.1977   1st Qu.:  0.14602   1st Qu.:  0.1458  
 Median :0.1977   Median :0.1977   Median :  0.19470   Median :  0.1947  
 Mean   :0.1977   Mean   :0.1977   Mean   :  0.28931   Mean   :  0.2827  
 3rd Qu.:0.1977   3rd Qu.:0.1977   3rd Qu.:  0.26326   3rd Qu.:  0.2633  
 Max.   :0.1977   Max.   :0.1977   Max.   :219.16288   Max.   :219.1629  
                                                       NA's   :2678      
 TD_Mi_SSHG_Med      TD_Mi_SSHG_Med_F    TD_Mi_Cnt        TD_Mi_Cnt_F     
 Min.   :  0.00019   Min.   :  0.000   Min.   :2486795   Min.   :2387406  
 1st Qu.:  0.14403   1st Qu.:  0.144   1st Qu.:2486795   1st Qu.:2387406  
 Median :  0.19527   Median :  0.195   Median :2486795   Median :2387406  
 Mean   :  0.29152   Mean   :  0.285   Mean   :2486795   Mean   :2387406  
 3rd Qu.:  0.26657   3rd Qu.:  0.266   3rd Qu.:2486795   3rd Qu.:2387406  
 Max.   :250.65606   Max.   :250.656   Max.   :2486795   Max.   :2387406  
                     NA's   :4904                                         
  TD_Mi_SS_Cnt    TD_Mi_SS_Cnt_F   TD_Mi_SSHG_Cnt   TD_Mi_SSHG_Cnt_F
 Min.   :   1.0   Min.   :   0.0   Min.   :  1.00   Min.   :  0.00  
 1st Qu.: 178.0   1st Qu.: 160.0   1st Qu.: 28.00   1st Qu.: 24.00  
 Median : 295.0   Median : 266.0   Median : 48.00   Median : 42.00  
 Mean   : 363.3   Mean   : 327.1   Mean   : 60.01   Mean   : 53.31  
 3rd Qu.: 476.0   3rd Qu.: 428.0   3rd Qu.: 78.00   3rd Qu.: 70.00  
 Max.   :1543.0   Max.   :1388.0   Max.   :663.00   Max.   :595.00  
                                                                    
 TravelTime_Sec    TT_Sec_q2    TT_Sec_q98   TT_Sec_SS_q5      TT_Sec_SS_q95     
 Min.   :    1   Min.   :10   Min.   :349   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   24   1st Qu.:10   1st Qu.:349   1st Qu.:   15.00   1st Qu.:   47.00  
 Median :   38   Median :10   Median :349   Median :   21.00   Median :   77.75  
 Mean   :  100   Mean   :10   Mean   :349   Mean   :   57.38   Mean   :  176.22  
 3rd Qu.:   70   3rd Qu.:10   3rd Qu.:349   3rd Qu.:   32.00   3rd Qu.:  129.65  
 Max.   :54551   Max.   :10   Max.   :349   Max.   :54551.00   Max.   :54551.00  
 NA's   :28                                                                      
 TT_Sec_SSHG_q5     TT_Sec_SSHG_q95     TT_Sec_Mean    TT_Sec_Mean_F  
 Min.   :    1.00   Min.   :    1.00   Min.   :104.9   Min.   :56.61  
 1st Qu.:   15.20   1st Qu.:   42.70   1st Qu.:104.9   1st Qu.:56.61  
 Median :   22.50   Median :   70.55   Median :104.9   Median :56.61  
 Mean   :   62.94   Mean   :  161.25   Mean   :104.9   Mean   :56.61  
 3rd Qu.:   34.80   3rd Qu.:  119.60   3rd Qu.:104.9   3rd Qu.:56.61  
 Max.   :54551.00   Max.   :54551.00   Max.   :104.9   Max.   :56.61  
                                                                      
 TT_Sec_SS_Mean     TT_Sec_SS_Mean_F   TT_Sec_SSHG_Mean   TT_Sec_SSHG_Mean_F
 Min.   :    1.00   Min.   :    1.00   Min.   :    1.00   Min.   :    1.00  
 1st Qu.:   28.20   1st Qu.:   26.62   1st Qu.:   27.51   1st Qu.:   26.34  
 Median :   42.61   Median :   40.46   Median :   41.76   Median :   39.96  
 Mean   :   99.62   Mean   :   86.96   Mean   :   99.55   Mean   :   88.81  
 3rd Qu.:   69.71   3rd Qu.:   66.44   3rd Qu.:   70.02   3rd Qu.:   67.22  
 Max.   :54551.00   Max.   :54551.00   Max.   :54551.00   Max.   :54551.00  
                    NA's   :2603                          NA's   :3772      
   TT_Sec_Med  TT_Sec_Med_F TT_Sec_SS_Med      TT_Sec_SS_Med_F   
 Min.   :39   Min.   :39    Min.   :    1.00   Min.   :    1.00  
 1st Qu.:39   1st Qu.:39    1st Qu.:   25.00   1st Qu.:   25.00  
 Median :39   Median :39    Median :   37.00   Median :   37.00  
 Mean   :39   Mean   :39    Mean   :   86.88   Mean   :   80.62  
 3rd Qu.:39   3rd Qu.:39    3rd Qu.:   62.00   3rd Qu.:   62.00  
 Max.   :39   Max.   :39    Max.   :54551.00   Max.   :54551.00  
                                               NA's   :2603      
 TT_Sec_SSHG_Med    TT_Sec_SSHG_Med_F    TT_Sec_Cnt       TT_Sec_Cnt_F    
 Min.   :    1.00   Min.   :    1.00   Min.   :2802888   Min.   :2705189  
 1st Qu.:   25.00   1st Qu.:   25.00   1st Qu.:2802888   1st Qu.:2705189  
 Median :   37.00   Median :   37.00   Median :2802888   Median :2705189  
 Mean   :   90.07   Mean   :   83.87   Mean   :2802888   Mean   :2705189  
 3rd Qu.:   64.00   3rd Qu.:   64.00   3rd Qu.:2802888   3rd Qu.:2705189  
 Max.   :54551.00   Max.   :54551.00   Max.   :2802888   Max.   :2705189  
                    NA's   :3772                                          
 TT_Sec_SS_Cnt    TT_Sec_SS_Cnt_F  TT_Sec_SSHG_Cnt TT_Sec_SSHG_Cnt_F
 Min.   :   1.0   Min.   :   0.0   Min.   :  1.0   Min.   :  0.00   
 1st Qu.: 200.0   1st Qu.: 183.0   1st Qu.: 30.0   1st Qu.: 27.00   
 Median : 321.0   Median : 292.0   Median : 52.0   Median : 47.00   
 Mean   : 392.4   Mean   : 357.2   Mean   : 64.7   Mean   : 58.23   
 3rd Qu.: 509.0   3rd Qu.: 464.0   3rd Qu.: 84.0   3rd Qu.: 76.00   
 Max.   :1664.0   Max.   :1523.0   Max.   :691.0   Max.   :634.00   
                                                                    
 TravelTime_Hr          TT_Hr_q2          TT_Hr_q98        TT_Hr_SS_q5       
 Min.   : 0.000278   Min.   :0.002778   Min.   :0.09694   Min.   : 0.000278  
 1st Qu.: 0.006667   1st Qu.:0.002778   1st Qu.:0.09694   1st Qu.: 0.004167  
 Median : 0.010556   Median :0.002778   Median :0.09694   Median : 0.005833  
 Mean   : 0.027782   Mean   :0.002778   Mean   :0.09694   Mean   : 0.015938  
 3rd Qu.: 0.019444   3rd Qu.:0.002778   3rd Qu.:0.09694   3rd Qu.: 0.008889  
 Max.   :15.153056   Max.   :0.002778   Max.   :0.09694   Max.   :15.153056  
 NA's   :28                                                                  
  TT_Hr_SS_q95       TT_Hr_SSHG_q5       TT_Hr_SSHG_q95        TT_Hr_Mean     
 Min.   : 0.000278   Min.   : 0.000278   Min.   : 0.000278   Min.   :0.02913  
 1st Qu.: 0.013056   1st Qu.: 0.004222   1st Qu.: 0.011861   1st Qu.:0.02913  
 Median : 0.021597   Median : 0.006250   Median : 0.019597   Median :0.02913  
 Mean   : 0.048950   Mean   : 0.017485   Mean   : 0.044792   Mean   :0.02913  
 3rd Qu.: 0.036014   3rd Qu.: 0.009667   3rd Qu.: 0.033222   3rd Qu.:0.02913  
 Max.   :15.153056   Max.   :15.153056   Max.   :15.153056   Max.   :0.02913  
                                                                              
  TT_Hr_Mean_F     TT_Hr_SS_Mean       TT_Hr_SS_Mean_F   TT_Hr_SSHG_Mean    
 Min.   :0.01573   Min.   : 0.000278   Min.   : 0.0003   Min.   : 0.000278  
 1st Qu.:0.01573   1st Qu.: 0.007832   1st Qu.: 0.0074   1st Qu.: 0.007643  
 Median :0.01573   Median : 0.011836   Median : 0.0112   Median : 0.011600  
 Mean   :0.01573   Mean   : 0.027673   Mean   : 0.0242   Mean   : 0.027654  
 3rd Qu.:0.01573   3rd Qu.: 0.019363   3rd Qu.: 0.0185   3rd Qu.: 0.019450  
 Max.   :0.01573   Max.   :15.153056   Max.   :15.1531   Max.   :15.153056  
                                       NA's   :2612                         
 TT_Hr_SSHG_Mean_F   TT_Hr_Med        TT_Hr_Med_F       TT_Hr_SS_Med      
 Min.   : 0.000    Min.   :0.01083   Min.   :0.01083   Min.   : 0.000278  
 1st Qu.: 0.007    1st Qu.:0.01083   1st Qu.:0.01083   1st Qu.: 0.006944  
 Median : 0.011    Median :0.01083   Median :0.01083   Median : 0.010278  
 Mean   : 0.025    Mean   :0.01083   Mean   :0.01083   Mean   : 0.024132  
 3rd Qu.: 0.019    3rd Qu.:0.01083   3rd Qu.:0.01083   3rd Qu.: 0.017222  
 Max.   :15.153    Max.   :0.01083   Max.   :0.01083   Max.   :15.153056  
 NA's   :3842                                                             
 TT_Hr_SS_Med_F    TT_Hr_SSHG_Med      TT_Hr_SSHG_Med_F   TT_Hr_Cnt      
 Min.   : 0.0003   Min.   : 0.000278   Min.   : 0.000   Min.   :2802888  
 1st Qu.: 0.0069   1st Qu.: 0.006944   1st Qu.: 0.007   1st Qu.:2802888  
 Median : 0.0103   Median : 0.010278   Median : 0.010   Median :2802888  
 Mean   : 0.0224   Mean   : 0.025019   Mean   : 0.023   Mean   :2802888  
 3rd Qu.: 0.0172   3rd Qu.: 0.017778   3rd Qu.: 0.018   3rd Qu.:2802888  
 Max.   :15.1531   Max.   :15.153056   Max.   :15.153   Max.   :2802888  
 NA's   :2612                          NA's   :3842                      
  TT_Hr_Cnt_F       TT_Hr_SS_Cnt    TT_Hr_SS_Cnt_F TT_Hr_SSHG_Cnt  TT_Hr_SSHG_Cnt_F
 Min.   :2705189   Min.   :   1.0   Min.   :   0   Min.   :  1.0   Min.   :  0.00  
 1st Qu.:2705189   1st Qu.: 200.0   1st Qu.: 183   1st Qu.: 30.0   1st Qu.: 27.00  
 Median :2705189   Median : 321.0   Median : 292   Median : 52.0   Median : 47.00  
 Mean   :2705189   Mean   : 392.4   Mean   : 357   Mean   : 64.7   Mean   : 58.19  
 3rd Qu.:2705189   3rd Qu.: 509.0   3rd Qu.: 464   3rd Qu.: 84.0   3rd Qu.: 76.00  
 Max.   :2705189   Max.   :1664.0   Max.   :1523   Max.   :691.0   Max.   :634.00  
                                                                                   
  SpeedAvg_Mph     
 Min.   :    0.00  
 1st Qu.:   10.10  
 Median :   16.68  
 Mean   :   26.54  
 3rd Qu.:   31.17  
 Max.   :22924.09  
 NA's   :28        

Investigation of TravelDistance_Mi.

Let’s plot just the TravelDistance_Mi values that are NOT “NA”.

TravDistMi_HistDen <- ggplot(select(TravelDistance_Mi_NoNA,
                                    TravelDistance_Mi
                                   ),
                             aes(x = TravelDistance_Mi,
                                 y = ..density..
                                )
                            ) +
  geom_histogram(binwidth = 0.05, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(0, 1.5), ylim = c(0, 4.0)
                 ) +
  labs(title = "Variation in Distance Between Stops",
       x = "Travel Distance (miles)",
       y = "Density"
      )
TravDistMi_HistDen

Investigation of TravelDistance_Mi.

Looking at the extremely large TravelDistance_Mi values. Some (aprox 27%) of TravelDistance_Mi values > 1 mile are when the DirChange2 changes…but what about the other ~73%?

rm(TravelDistance_Mi_NoNA)
# examples of weirdly large TravelDistance_Mi
View(filter(AllDays_NewOrder,
            TravelDistance_Mi > 1.1587121212 # 1.1587121212 is the 99th percentile
           ) %>% 
       arrange(desc(TravelDistance_Mi)
              )
    )
# Why are these extremes?  Airports?  Bus collection points?
View(filter(AllDays_NewOrder,
              between(RowNum_OG, 494044, 494064) | # 494054
              between(RowNum_OG, 494273, 494293) | # 494283
              between(RowNum_OG, 494626, 494646) | # 494636
              between(RowNum_OG, 1610156, 1610176) | # 1610166
              between(RowNum_OG, 2073074, 2073094) # 2073084
           )
    )
# Before Removing Runs
# View(filter(AllDays_Sorted,
#             between(RowNum_OG, 494044, 494064) | # 494054
#               between(RowNum_OG, 494273, 494293) | # 494283
#               between(RowNum_OG, 494626, 494646) | # 494636
#               between(RowNum_OG, 1610156, 1610176) | # 1610166
#               between(RowNum_OG, 2073074, 2073094) # 2073084
#            )
#     )
# After Removing Runs
# View(filter(AllDays_FirstStopID,
#             between(RowNum_OG, 494044, 494064) | # 494054
#               between(RowNum_OG, 494273, 494293) | # 494283
#               between(RowNum_OG, 494626, 494646) | # 494636
#               between(RowNum_OG, 1610156, 1610176) | # 1610166
#               between(RowNum_OG, 2073074, 2073094) # 2073084
#            )
#     )

Investigation of TravelDistance_Mi.

Any relation with DirChange2? Doesn’t look as if this is so.

ExtremeTravDist <- filter(AllDays_NewOrder,
                          !is.na(TravelDistance_Mi)
                         ) %>% 
  mutate(TravDist_Extreme = ifelse(TravelDistance_Mi > 1.1587121212, # 1.1587121212 is the 99th percentile
                                   "True",
                                   "False"
                                  )
                          ) %>% 
  group_by(DirChange2, TravDist_Extreme) %>% 
  summarise(TravDistMI_ExtCnts = n()
           )
# ExtremeTravDist
ExtremeTravDist_Spread <- as.data.frame(spread(ExtremeTravDist,
                                               TravDist_Extreme,
                                               TravDistMI_ExtCnts
                                              )
                                       ) %>% 
  select(False,
         True
        )
row.names(ExtremeTravDist_Spread) <- c("Change", "Same")
# str(ExtremeTravDist_Spread)
# ExtremeTravDist_Spread
prop.table(as.table(as.matrix(ExtremeTravDist_Spread)
                   ),
           1
          )
            False       True
Change 0.80622587 0.19377413
Same   0.98855456 0.01144544
prop.table(as.table(as.matrix(ExtremeTravDist_Spread)
                   ),
           2
          )
            False       True
Change 0.01594448 0.25169594
Same   0.98405552 0.74830406

Investigation of TravelDistance_Mi.

Looking at specific buses and StartStop_ID.

rm(ExtremeTravDist, ExtremeTravDist_Spread)
View(arrange(group_by(AllDays_NewOrder,
                      Bus_ID
                     ) %>% 
               summarise(DistTrav_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
                         DistTrav_Med = median(TravelDistance_Mi, na.rm = TRUE)
                        ),
             desc(DistTrav_Med)
            )
    )
# example of extremely small TravelDistance_Mi values (looks like the odometer wasn't functioning)
View(filter(AllDays_NewOrder,
            Bus_ID == 6111 |
              Bus_ID == 7201 |
              Bus_ID == 8058
           ) %>% 
       arrange(Bus_ID, Event_Time)
    )
View(arrange(group_by(AllDays_NewOrder,
                      StartStop_ID
                     ) %>% 
               summarise(DistTrav_Mean = mean(TravelDistance_Mi, na.rm = TRUE),
                         DistTrav_Med = median(TravelDistance_Mi, na.rm = TRUE)
                        ),
             desc(DistTrav_Med)
            )
    )
# example of extremely large TravelDistance_Mi values...no idea why...
View(filter(AllDays_NewOrder,
            StartStop_ID == "1003665--12" |
              StartStop_ID == "1003665--5001925" |
              StartStop_ID == "3001038--3002565"
           ) %>% 
       arrange(StartStop_ID, Event_Time)
    )

Investigation of TravelDistance_Mi & TravelDistance_Mi_New.

If TravelDisntace_Mi is below the 5th percentile for that StartStop_ID, or if TravelDisntace_Mi is above the 95th percentile for that StartStop_ID, or if TravelDistance_Mi is NA (when the BusDay_EventNum !=1), consider this an outlier. In this case, replace the value with the mean for that StartStop_ID and HourGroup (TD_Mi_SSHG_Mean_F), or if there are not enough values at the HourGroup level, replace it with the mean for that StartStop_ID.

# View(tail(AllDays_NewOrder, 500))
AllDays_NewTravelDist <- 
  mutate(AllDays_NewOrder,
         TravelDistance_Mi_New = ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SSHG_Cnt_F >= 20,
                                        TD_Mi_SSHG_Mean_F,
                                 ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SSHG_Cnt_F < 20 &
                                          TD_Mi_SS_Cnt_F >= 20,
                                        TD_Mi_SS_Mean_F,
                                 ifelse(!is.na(TravelDistance_Mi) & 
                                          (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                                             TravelDistance_Mi > TD_Mi_SSHG_q95
                                          ) &
                                          TD_Mi_SS_Cnt_F < 20 &
                                          TD_Mi_SS_Cnt >= 20,
                                        TD_Mi_SS_Mean,
                                 ifelse(is.na(TravelDistance_Mi) &
                                          BusDay_EventNum != 1 &
                                          TravelDistance_Mi_Hvrs != 0,
                                        TravelDistance_Mi_Hvrs,
                                 ifelse(is.na(TravelDistance_Mi) &
                                          BusDay_EventNum != 1 &
                                          TravelDistance_Mi_Hvrs == 0,
                                        TD_Mi_SS_Mean,
                                        TravelDistance_Mi
                                       ))))),
         TravelDistance_Mi_New_Label = 
           factor(ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SSHG_Cnt_F >= 20,
                         "TD_Mi_SSHG_Mean_F",
                  ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SSHG_Cnt_F < 20 &
                           TD_Mi_SS_Cnt_F >= 20,
                         "TD_Mi_SS_Mean_F",
                  ifelse(!is.na(TravelDistance_Mi) &
                           (TravelDistance_Mi < TD_Mi_SSHG_q5 |
                              TravelDistance_Mi > TD_Mi_SSHG_q95
                           ) &
                           TD_Mi_SS_Cnt_F < 20 &
                           TD_Mi_SS_Cnt >= 20,
                         "TD_Mi_SS_Mean",
                  ifelse(is.na(TravelDistance_Mi) &
                           BusDay_EventNum != 1 &
                           TravelDistance_Mi_Hvrs != 0,
                         "TravelDistance_Mi_Hvrs",
                  ifelse(is.na(TravelDistance_Mi) &
                           BusDay_EventNum != 1 &
                           TravelDistance_Mi_Hvrs == 0,
                         "TD_Mi_SS_Mean",
                         "TravelDistance_Mi"
                        )))))
                 ),
         TravelDistance_Mi_NewHvrs = ifelse(!is.na(TravelDistance_Mi_Hvrs) &
                                              TravelDistance_Mi_Hvrs != 0 &
                                              (TravelDistance_Mi_New < TD_Mi_q2 |
                                                 TravelDistance_Mi_New > TD_Mi_q98
                                              ),
                                            TravelDistance_Mi_Hvrs,
                                            TravelDistance_Mi_New
                                           ),
         TravelDistance_Mi_NewHvrs_Label =
           factor(ifelse(!is.na(TravelDistance_Mi_Hvrs) &
                           TravelDistance_Mi_Hvrs != 0 &
                           (TravelDistance_Mi_New < TD_Mi_q2 |
                              TravelDistance_Mi_New > TD_Mi_q98
                           ),
                         "TravelDistance_Mi_Hvrs",
                         as.character(TravelDistance_Mi_New_Label)
                        )
                 ),
         SpeedAvg_Mph_NewHvrs = TravelDistance_Mi_NewHvrs / TravelTime_Hr
        )
str(AllDays_NewTravelDist)
'data.frame':   2809529 obs. of  119 variables:
 $ RowNum_OG                      : int  1 3 4 5 6 7 9 10 11 12 ...
 $ group                          : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID                   : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                         : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                          : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2                     : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt                       : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2                     : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction                : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence                  : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID                       : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc                     : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean                   : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator               : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc                      : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type                     : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description              : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr                  : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth                 : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date                : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day                 : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr                  : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup             : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min                 : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time                     : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time                 : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time                     : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2                    : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time                     : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude                       : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude                      : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading                        : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance              : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1         : int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi           : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft              : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi              : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs         : num  NA 0.15 0.105 0.165 0.832 ...
 $ TD_Mi_q2                       : num  0.0521 0.0521 0.0521 0.0521 0.0521 ...
 $ TD_Mi_q98                      : num  0.959 0.959 0.959 0.959 0.959 ...
 $ TD_Mi_SS_q5                    : num  NA 0.0252 0.2422 0.7324 0.0794 ...
 $ TD_Mi_SS_q95                   : num  NA 0.626 0.242 1.008 0.176 ...
 $ TD_Mi_SSHG_q5                  : num  NA 0.0996 0.2422 0.7002 0.1816 ...
 $ TD_Mi_SSHG_q95                 : num  NA 0.627 0.242 0.7 0.182 ...
 $ TD_Mi_Mean                     : num  0.308 0.308 0.308 0.308 0.308 ...
 $ TD_Mi_Mean_F                   : num  0.232 0.232 0.232 0.232 0.232 ...
 $ TD_Mi_SS_Mean                  : num  NaN 0.437 0.242 0.908 0.128 ...
 $ TD_Mi_SS_Mean_F                : num  NaN 0.457 0.242 0.977 NaN ...
 $ TD_Mi_SSHG_Mean                : num  NaN 0.442 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Mean_F              : num  NaN 0.491 0.242 0.7 0.182 ...
 $ TD_Mi_Med                      : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_Med_F                    : num  0.198 0.198 0.198 0.198 0.198 ...
 $ TD_Mi_SS_Med                   : num  NA 0.512 0.242 0.962 0.128 ...
 $ TD_Mi_SS_Med_F                 : num  NA 0.512 0.242 1.008 NA ...
 $ TD_Mi_SSHG_Med                 : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_SSHG_Med_F               : num  NA 0.512 0.242 0.7 0.182 ...
 $ TD_Mi_Cnt                      : int  2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 2486795 ...
 $ TD_Mi_Cnt_F                    : int  2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 2387406 ...
 $ TD_Mi_SS_Cnt                   : int  0 14 1 4 2 87 22 118 91 11 ...
 $ TD_Mi_SS_Cnt_F                 : int  0 12 1 3 0 77 18 106 81 9 ...
 $ TD_Mi_SSHG_Cnt                 : int  0 7 1 1 1 23 6 29 28 3 ...
 $ TD_Mi_SSHG_Cnt_F               : int  0 5 1 1 1 19 4 25 24 1 ...
 $ TravelTime_Sec                 : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TT_Sec_q2                      : num  10 10 10 10 10 10 10 10 10 10 ...
 $ TT_Sec_q98                     : num  349 349 349 349 349 349 349 349 349 349 ...
 $ TT_Sec_SS_q5                   : num  NA 11.9 37 30.5 172.9 ...
 $ TT_Sec_SS_q95                  : num  NA 346.3 37 75.8 189.1 ...
 $ TT_Sec_SSHG_q5                 : num  NA 59.6 37 25 190 11.6 236 51.5 55 8.8 ...
 $ TT_Sec_SSHG_q95                : num  NA 276 37 25 190 ...
 $ TT_Sec_Mean                    : num  105 105 105 105 105 ...
 $ TT_Sec_Mean_F                  : num  56.6 56.6 56.6 56.6 56.6 ...
 $ TT_Sec_SS_Mean                 : num  NaN 215.8 37 58.2 181 ...
 $ TT_Sec_SS_Mean_F               : num  NaN 218.9 37 65.5 NaN ...
 $ TT_Sec_SSHG_Mean               : num  NaN 202 37 25 190 ...
 $ TT_Sec_SSHG_Mean_F             : num  NaN 226 37 25 190 ...
 $ TT_Sec_Med                     : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_Med_F                   : num  39 39 39 39 39 39 39 39 39 39 ...
 $ TT_Sec_SS_Med                  : num  NA 223.5 37 65.5 181 ...
 $ TT_Sec_SS_Med_F                : num  NA 223.5 37 65.5 NA ...
 $ TT_Sec_SSHG_Med                : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_SSHG_Med_F              : num  NA 219 37 25 190 134 286 60 65 16 ...
 $ TT_Sec_Cnt                     : int  2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 2802888 ...
 $ TT_Sec_Cnt_F                   : int  2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 2705189 ...
 $ TT_Sec_SS_Cnt                  : int  0 14 1 4 2 173 22 141 141 11 ...
 $ TT_Sec_SS_Cnt_F                : int  0 12 1 2 0 156 18 127 128 9 ...
 $ TT_Sec_SSHG_Cnt                : int  0 7 1 1 1 35 6 36 35 3 ...
 $ TT_Sec_SSHG_Cnt_F              : int  0 5 1 1 1 31 4 32 32 1 ...
 $ TravelTime_Hr                  : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ TT_Hr_q2                       : num  0.00278 0.00278 0.00278 0.00278 0.00278 ...
 $ TT_Hr_q98                      : num  0.0969 0.0969 0.0969 0.0969 0.0969 ...
 $ TT_Hr_SS_q5                    : num  NA 0.00331 0.01028 0.00849 0.04803 ...
 $ TT_Hr_SS_q95                   : num  NA 0.0962 0.0103 0.0211 0.0525 ...
 $ TT_Hr_SSHG_q5                  : num  NA 0.01656 0.01028 0.00694 0.05278 ...
 $ TT_Hr_SSHG_q95                 : num  NA 0.07653 0.01028 0.00694 0.05278 ...
 $ TT_Hr_Mean                     : num  0.0291 0.0291 0.0291 0.0291 0.0291 ...
 $ TT_Hr_Mean_F                   : num  0.0157 0.0157 0.0157 0.0157 0.0157 ...
 $ TT_Hr_SS_Mean                  : num  NaN 0.0599 0.0103 0.0162 0.0503 ...
 $ TT_Hr_SS_Mean_F                : num  NaN 0.0608 0.0103 0.0182 NaN ...
  [list output truncated]

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Quick summary and then correlation calculation.

rm(AllDays_NewOrder)
# 38 rows meet this criteria anymore  --  appears to be the case when both the Lat Long calculations, and the TravelDistance calculations did not function properly.
View(filter(AllDays_NewTravelDist,
            is.na(TravelDistance_Mi_New) &
              BusDay_EventNum != 1
           )
    )
View(AllDays_NewTravelDist %>% 
       arrange(desc(TravelDistance_Mi_New)) %>% 
       head(500)
    )
summary(select(AllDays_NewTravelDist,
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.0     Min.   : 0.000         Min.   :  0.000      
 1st Qu.:  0.1     1st Qu.: 0.106         1st Qu.:  0.141      
 Median :  0.2     Median : 0.142         Median :  0.199      
 Mean   :  0.3     Mean   : 0.201         Mean   :  0.298      
 3rd Qu.:  0.3     3rd Qu.: 0.193         3rd Qu.:  0.276      
 Max.   :250.7     Max.   :24.407         Max.   :250.656      
 NA's   :322734    NA's   :6528           NA's   :6566         
 TravelDistance_Mi_NewHvrs
 Min.   : 0.000           
 1st Qu.: 0.142           
 Median : 0.199           
 Mean   : 0.259           
 3rd Qu.: 0.276           
 Max.   :36.236           
 NA's   :6566             
summary(select(filter(AllDays_NewTravelDist,
                      BusDay_EventNum != 1
                     ),
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.00    Min.   : 0.0000        Min.   :  0.00019    
 1st Qu.:  0.13    1st Qu.: 0.1055        1st Qu.:  0.14072    
 Median :  0.20    Median : 0.1424        Median :  0.19867    
 Mean   :  0.31    Mean   : 0.2008        Mean   :  0.29751    
 3rd Qu.:  0.29    3rd Qu.: 0.1935        3rd Qu.:  0.27633    
 Max.   :250.66    Max.   :24.4068        Max.   :250.65606    
 NA's   :316206                           NA's   :38           
 TravelDistance_Mi_NewHvrs
 Min.   : 0.00019         
 1st Qu.: 0.14205         
 Median : 0.19903         
 Mean   : 0.25859         
 3rd Qu.: 0.27557         
 Max.   :36.23636         
 NA's   :38               
cor(select(AllDays_NewTravelDist,
           TravelDistance_Mi,
           TravelDistance_Mi_Hvrs,
           TravelDistance_Mi_New,
           TravelDistance_Mi_NewHvrs
          ),
    use = "pairwise.complete.obs"
  )
                          TravelDistance_Mi TravelDistance_Mi_Hvrs
TravelDistance_Mi                 1.0000000              0.5447660
TravelDistance_Mi_Hvrs            0.5447660              1.0000000
TravelDistance_Mi_New             0.9513379              0.5837182
TravelDistance_Mi_NewHvrs         0.6005944              0.9005277
                          TravelDistance_Mi_New TravelDistance_Mi_NewHvrs
TravelDistance_Mi                     0.9513379                 0.6005944
TravelDistance_Mi_Hvrs                0.5837182                 0.9005277
TravelDistance_Mi_New                 1.0000000                 0.6346981
TravelDistance_Mi_NewHvrs             0.6346981                 1.0000000

Investigation of TravelDistance_Mi_NewHvrs_Label & TravelDistance_Mi_NewHvrs_Label.

Show how the labels changed.

group_by(AllDays_NewTravelDist,
         TravelDistance_Mi_New_Label,
         TravelDistance_Mi_NewHvrs_Label
        ) %>% 
  summarise(CntNum = n(),
            CntPct = format(CntNum / nrow(AllDays_NewTravelDist),
                            scientific = 9999
                           )
           ) %>% 
  arrange(desc(CntPct)
         )

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Graphing the two methods of calculating TravelDistance_Mi.

First, let’s get create a function to plot the liner model equation.

lm_eqn <- function(df, y, x){
  m <- lm(y ~ x, df)
  
  l <- list(a = format(coef(m)[1], digits = 2),
            b = format(abs(coef(m)[2]), digits = 2),
            s1 = ifelse(test = coef(m)[2] > 0,
                        yes = "+",
                        no = "-"
                       ),
            r2 = format(summary(m)$r.squared,
                        digits = 3
                       )
           )
  
  eq <- substitute(italic(y) == a~~s1~~b %.% italic(x)*","~~italic(r)^2~"="~r2,
                   l
                  )
  
  as.character(as.expression(eq)
              )             
}

Investigation of TravelDistance_Mi & TravelDistance_Mi_NewHvrs.

Scatter plot (using a 10% sample to making plotting time faster and to reduce un-needed data in the “same” splot).

set.seed(123456789)
AllDays_NewTravelDist_10Pct <- filter(AllDays_NewTravelDist,
                                      !is.na(TravelDistance_Mi_NewHvrs) &
                                        !is.na(TravelDistance_Mi)
                                     ) %>% 
  rename(DistMethod = TravelDistance_Mi_NewHvrs_Label) %>% 
  sample_frac(0.1)
TravDist_MiVsCalc <- ggplot(select(AllDays_NewTravelDist_10Pct,
                                   TravelDistance_Mi_NewHvrs,
                                   TravelDistance_Mi,
                                   DistMethod
                                  ),
                            aes(x = TravelDistance_Mi,
                                y = TravelDistance_Mi_NewHvrs,
                                colour = DistMethod
                               )
                           ) +
  scale_colour_manual(values = c("red","blue", "green", "orange", "black")
                     ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "blue") +
  geom_abline(intercept = 0, slope = 1, colour = "red") +
  coord_cartesian(xlim = c(0, 1.5), ylim = c(0, 1.5)
                 ) +
  scale_x_continuous(breaks = seq(0, 1.5, 0.25)
                    ) +
  scale_y_continuous(breaks = seq(0, 1.5, 0.25)
                    ) +
  theme(legend.position = "bottom", #c(0.85, 0.40),
        legend.text = element_text(size = 6)
       ) +
  annotate(label = lm_eqn(df = AllDays_NewTravelDist_10Pct,
                          x = AllDays_NewTravelDist_10Pct$TravelDistance_Mi,
                          y = AllDays_NewTravelDist_10Pct$TravelDistance_Mi_NewHvrs
                         ),
           # x = 62,
           # y = 20,
           x = 0.70,
           y = 0.00,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  annotate(label = "Reference Line (slope = 1)",
           # x = 16,
           # y = 30,
           x = 0.80,
           y = 1.05,
           geom = "text",
           size = 3,
           colour = "red"
          ) +
  labs(title = "TravelDistance_Mi vs. TravelDistance_Mi_NewHvrs",
       x = "TravelDistance_Mi",
       y = "TravelDistance_Mi_NewHvrs"
      )
# +
#   geom_jitter()
TravDist_MiVsCalc

Investigation of TravelDistance_Mi & TravelDistance_Mi_Hvrs & TravelDistance_Mi_New.

Graphing test with rbokeh.

TravDist_MiVsCalc_Bokeh <- figure(data = select(AllDays_NewTravelDist_10Pct,
                                                TravelDistance_Mi_NewHvrs,
                                                TravelDistance_Mi,
                                                DistMethod
                                               ),
                                  xlim = c(0, 1.5),
                                  ylim = c(0, 1.5),
                                  legend_location = "bottom_right"
                                 ) %>% 
  ly_points(x = TravelDistance_Mi,
            y = TravelDistance_Mi_NewHvrs,
            color = DistMethod,
            hover = c(TravelDistance_Mi_NewHvrs, TravelDistance_Mi, DistMethod)
           ) %>% 
  ly_abline(a = 0, b = 1, color = "red")
TravDist_MiVsCalc_Bokeh

Investigation of TravelDistance_Mi_New.

Calculating the minimum TravelDistance_Mi_New value at each percentile.

rm(TravDist_MiVsCalc_Bokeh)
rm(AllDays_NewTravelDist_10Pct)
summary(select(AllDays_NewTravelDist,
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.0     Min.   : 0.000         Min.   :  0.000      
 1st Qu.:  0.1     1st Qu.: 0.106         1st Qu.:  0.141      
 Median :  0.2     Median : 0.142         Median :  0.199      
 Mean   :  0.3     Mean   : 0.201         Mean   :  0.298      
 3rd Qu.:  0.3     3rd Qu.: 0.193         3rd Qu.:  0.276      
 Max.   :250.7     Max.   :24.407         Max.   :250.656      
 NA's   :322734    NA's   :6528           NA's   :6566         
 TravelDistance_Mi_NewHvrs
 Min.   : 0.000           
 1st Qu.: 0.142           
 Median : 0.199           
 Mean   : 0.259           
 3rd Qu.: 0.276           
 Max.   :36.236           
 NA's   :6566             
summary(select(filter(AllDays_NewTravelDist,
                      BusDay_EventNum != 1
                     ),
               TravelDistance_Mi,
               TravelDistance_Mi_Hvrs,
               TravelDistance_Mi_New,
               TravelDistance_Mi_NewHvrs
              )
       )
 TravelDistance_Mi TravelDistance_Mi_Hvrs TravelDistance_Mi_New
 Min.   :  0.00    Min.   : 0.0000        Min.   :  0.00019    
 1st Qu.:  0.13    1st Qu.: 0.1055        1st Qu.:  0.14072    
 Median :  0.20    Median : 0.1424        Median :  0.19867    
 Mean   :  0.31    Mean   : 0.2008        Mean   :  0.29751    
 3rd Qu.:  0.29    3rd Qu.: 0.1935        3rd Qu.:  0.27633    
 Max.   :250.66    Max.   :24.4068        Max.   :250.65606    
 NA's   :316206                           NA's   :38           
 TravelDistance_Mi_NewHvrs
 Min.   : 0.00019         
 1st Qu.: 0.14205         
 Median : 0.19903         
 Mean   : 0.25859         
 3rd Qu.: 0.27557         
 Max.   :36.23636         
 NA's   :38               
TravDistMiN_Ntile <- as.data.frame(select(AllDays_NewTravelDist,
                                          StartStop_ID,
                                          TravelDistance_Mi_New_Label,
                                          # TravelDistance_Mi_NewHvrs_Label,
                                          TravelDistance_Mi_New
                                          # TravelDistance_Mi_NewHvrs
                                         )
                                  ) %>% 
  mutate(PctR_N = percent_rank(AllDays_NewTravelDist$TravelDistance_Mi_New),
         # PctR_H = percent_rank(AllDays_NewTravelDist$TravelDistance_Mi_NewHvrs),
         PctR_Round_N = round(PctR_N, 2)
         # PctR_Round_H = round(PctR_H, 2)
        ) 
# str(TravDistMiN_Ntile)
# View(head(TravDistMiN_Ntile, 500))
TravDistMiN_Ntile_Rows <- nrow(TravDistMiN_Ntile)
# View(tail(TravDistMiN_Ntile, 500))
TravDistMiN_Pctiles <- group_by(TravDistMiN_Ntile,
                                PctR_Round_N
                               ) %>% 
  summarise(
    MinTDMiAtPctile_N = min(TravelDistance_Mi_New),
    # MinTDMiAtPctile_H = min(TravelDistance_Mi_NewHvrs),
    CntsAtPctile_N = sum(!is.na(TravelDistance_Mi_New)),
    # CntsAtPctile_H = sum(!is.na(TravelDistance_Mi_NewHvrs)),
    PctsAtPctile_N = CntsAtPctile_N / TravDistMiN_Ntile_Rows
    # PctsAtPctile_H = CntsAtPctile_H / TravDistMiN_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP_N = cumsum(PctsAtPctile_N)
         # CumSumPAtP_H = cumsum(PctsAtPctile_H)
        )
# View(TravDistMiN_Pctiles)

Investigation of TravelDistance_Mi_NewHvrs

Calculating the minimum TravelDistance_Mi_NewHvrs value at each percentile.

TravDistMiH_Ntile <- as.data.frame(select(AllDays_NewTravelDist,
                                          StartStop_ID,
                                          # TravelDistance_Mi_New_Label,
                                          TravelDistance_Mi_NewHvrs_Label,
                                          # TravelDistance_Mi_New,
                                          TravelDistance_Mi_NewHvrs
                                         )
                                  ) %>% 
  mutate(# PctR_N = percent_rank(AllDays_NewTravelDist$TravelDistance_Mi_New),
         PctR_H = percent_rank(AllDays_NewTravelDist$TravelDistance_Mi_NewHvrs),
         # PctR_Round_N = round(PctR_N, 2),
         PctR_Round_H = round(PctR_H, 2)
        ) 
# str(TravDistMiH_Ntile)
# View(head(TravDistMiH_Ntile, 500))
TravDistMiH_Ntile_Rows <- nrow(TravDistMiH_Ntile)
# View(tail(TravDistMiH_Ntile, 500))
TravDistMiH_Pctiles <- group_by(TravDistMiH_Ntile,
                                PctR_Round_H
                               ) %>% 
  summarise(
    # MinTDMiAtPctile_N = min(TravelDistance_Mi_New),
    MinTDMiAtPctile_H = min(TravelDistance_Mi_NewHvrs),
    # CntsAtPctile_N = sum(!is.na(TravelDistance_Mi_New)),
    CntsAtPctile_H = sum(!is.na(TravelDistance_Mi_NewHvrs)),
    # PctsAtPctile_N = CntsAtPctile_N / TravDistMiH_Ntile_Rows,
    PctsAtPctile_H = CntsAtPctile_H / TravDistMiH_Ntile_Rows
  ) %>% 
  mutate(# CumSumPAtP_N = cumsum(PctsAtPctile_N),
         CumSumPAtP_H = cumsum(PctsAtPctile_H)
        )
# View(TravDistMiH_Pctiles)

Join TravDistMiH_Pctiles, TravDistMiN_Pctiles, and TravDistMi_Pctiles.

~11% of rides are still showing as less than 0.1 miles of TravelDistance_Mi_NewHvrs.

rm(TravDistMiN_Ntile_Rows, TravDistMiH_Ntile_Rows, TravDistMiN_Ntile, TravDistMiH_Ntile)
# View(TravDistMi_Pctiles)
# View(TravDistMiN_Pctiles)
# View(TravDistMiH_Pctiles)
TravDistMi_Pctiles_All <- inner_join(x = TravDistMi_Pctiles,
                                     y = TravDistMiN_Pctiles,
                                     by = c("PctR_Round" = "PctR_Round_N")
                                    ) %>% 
  inner_join(y = TravDistMiH_Pctiles,
             by = c("PctR_Round" = "PctR_Round_H")
            ) %>% 
  select(PctR_Round,
         MinTravDistMiAtPctile,
         MinTDMiAtPctile_N,
         MinTDMiAtPctile_H,
         CntsAtPctile,
         CntsAtPctile_N,
         CntsAtPctile_H,
         PctsAtPctile,
         PctsAtPctile_N,
         PctsAtPctile_H,
         CumSumPAtP,
         CumSumPAtP_N,
         CumSumPAtP_H
         )
# str(TravDistMi_Pctiles_All)
rm(TravDistMi_Pctiles, TravDistMiN_Pctiles,TravDistMiH_Pctiles)
View(TravDistMi_Pctiles_All)
TravDistMi_Pctiles_All

Investigation of TravelDistance_Mi_New.

Why are there still some small or large TravelDistance_Mi_NewHvrs values.

# View(filter(AllDays_NewTravelDist,
#             !is.na(TravelDistance_Mi_NewHvrs)
#            ) %>% 
#        select(-TD_Mi_q2,
#               -TD_Mi_q98,
#               -TD_Mi_SS_q5,
#               -TD_Mi_SS_q95,
#               -TD_Mi_SSHG_q5,
#               -TD_Mi_SSHG_q95,
#               -TD_Mi_Mean,
#               -TD_Mi_Mean_F,
#               -TD_Mi_SS_Mean,
#               -TD_Mi_SS_Mean_F,
#               -TD_Mi_SSHG_Mean,
#               -TD_Mi_SSHG_Mean_F,
#               -TD_Mi_Med,
#               -TD_Mi_Med_F,
#               -TD_Mi_SS_Med,
#               -TD_Mi_SS_Med_F,
#               -TD_Mi_SSHG_Med,
#               -TD_Mi_SSHG_Med_F,
#               -TD_Mi_Cnt,
#               -TD_Mi_Cnt_F,
#               -TD_Mi_SS_Cnt,
#               -TD_Mi_SS_Cnt_F,
#               -TD_Mi_SSHG_Cnt,
#               -TD_Mi_SSHG_Cnt_F,
#               -TT_Sec_q2,
#               -TT_Sec_q98,
#               -TT_Sec_SS_q5,
#               -TT_Sec_SS_q95,
#               -TT_Sec_SSHG_q5,
#               -TT_Sec_SSHG_q95,
#               -TT_Sec_Mean,
#               -TT_Sec_Mean_F,
#               -TT_Sec_SS_Mean,
#               -TT_Sec_SS_Mean_F,
#               -TT_Sec_SSHG_Mean,
#               -TT_Sec_SSHG_Mean_F,
#               -TT_Sec_Med,
#               -TT_Sec_Med_F,
#               -TT_Sec_SS_Med,
#               -TT_Sec_SS_Med_F,
#               -TT_Sec_SSHG_Med,
#               -TT_Sec_SSHG_Med_F,
#               -TT_Sec_Cnt,
#               -TT_Sec_Cnt_F,
#               -TT_Sec_SS_Cnt,
#               -TT_Sec_SS_Cnt_F,
#               -TT_Sec_SSHG_Cnt,
#               -TT_Sec_SSHG_Cnt_F,
#               -TT_Hr_q2,
#               -TT_Hr_q98,
#               -TT_Hr_SS_q5,
#               -TT_Hr_SS_q95,
#               -TT_Hr_SSHG_q5,
#               -TT_Hr_SSHG_q95,
#               -TT_Hr_Mean,
#               -TT_Hr_Mean_F,
#               -TT_Hr_SS_Mean,
#               -TT_Hr_SS_Mean_F,
#               -TT_Hr_SSHG_Mean,
#               -TT_Hr_SSHG_Mean_F,
#               -TT_Hr_Med,
#               -TT_Hr_Med_F,
#               -TT_Hr_SS_Med,
#               -TT_Hr_SS_Med_F,
#               -TT_Hr_SSHG_Med,
#               -TT_Hr_SSHG_Med_F,
#               -TT_Hr_Cnt,
#               -TT_Hr_Cnt_F,
#               -TT_Hr_SS_Cnt,
#               -TT_Hr_SS_Cnt_F,
#               -TT_Hr_SSHG_Cnt,
#               -TT_Hr_SSHG_Cnt_F
#              ) %>% 
#        arrange(TravelDistance_Mi_NewHvrs) %>% 
#        head(500)
#     )
View(filter(AllDays_NewTravelDist,
            !is.na(TravelDistance_Mi_NewHvrs)
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
             ) %>% 
       arrange(TravelDistance_Mi_NewHvrs) %>%
       head(500)
    )
# examples of the smallest TravelDistance_Mi_NewHvrs values.
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 1424440 & RowNum_OG <= 1424460) | # 1424450  --  direction change
                (RowNum_OG >= 763292 & RowNum_OG <= 763312) | # 763302  --  direction change
                (RowNum_OG >= 1679093 & RowNum_OG <= 1679113) | # 1679103  --  direction change
                (RowNum_OG >= 2860918 & RowNum_OG <= 2860938) # 2860928  --  looks correct
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
             )
    )
View(filter(AllDays_NewTravelDist,
            !is.na(TravelDistance_Mi_NewHvrs)
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
             ) %>% 
       arrange(desc(TravelDistance_Mi_NewHvrs)
              ) %>%
       head(500)
    )
# examples of the largest TravelDistance_Mi_NewHvrs values.
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 1092000 & RowNum_OG <= 1092050) | # 1092030  --  direction change
                (RowNum_OG >= 1609460 & RowNum_OG <= 1609480) | # 1609470  -- direction change 
                (RowNum_OG >= 508904 & RowNum_OG <= 508924) | # 508914  --  direction change & original StopID was bad
                (RowNum_OG >= 2476345 & RowNum_OG <= 2476365) # 2476355  --  direction change
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
             )
    )

Investigation of TravelTime_Hr.

View(TravDistMi_Pctiles): 98% of TravelTime_Hr are between 7 seconds and 464 seconds (~8 minutes).

TravTimeHr_Ntile <- select(AllDays_NewTravelDist,
                           TravelTime_Hr
                          ) %>% 
  mutate(# Pctile = ntile(AllDays_NewTravelDist$TravelTime_Hr, 100),
         # MinR = min_rank(AllDays_NewTravelDist$TravelTime_Hr),
         PctR = percent_rank(AllDays_NewTravelDist$TravelTime_Hr),
         PctR_Round = round(PctR, 2)
        ) 
# str(TravTimeHr_Ntile)
TravTimeHr_Ntile_Rows <- nrow(TravTimeHr_Ntile)
# View(tail(TravTimeHr_Ntile, 500))
TravTimeHr_Pctiles <- group_by(TravTimeHr_Ntile,
                               PctR_Round
                              ) %>% 
  summarise(
    MinTravTimeHrAtPctile = min(TravelTime_Hr),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / TravTimeHr_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile),
         MinTravTimeSecAtPctile = MinTravTimeHrAtPctile * 3600
        )
rm(TravTimeHr_Ntile_Rows)
rm(TravTimeHr_Ntile)
View(TravTimeHr_Pctiles)
TravTimeHr_Pctiles

Investigation of TravelTime_Hr.

Histogram of TravelTime_Sec.

TravTime_Sec_HistDen <- ggplot(filter(select(AllDays_NewTravelDist,
                                             TravelTime_Sec
                                            ),
                                      !is.na(TravelTime_Sec)
                                     ),
                               aes(x = TravelTime_Sec,
                                   y = ..density..
                                  )
                          ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  # stat_bin(binwidth = 5,
  #          geom = "text",
  #          size = 2.5,
  #          vjust = 1.5,
  #          aes(label = format(..count.., big.mark = ",")
  #             ),
  #         ) +
  coord_cartesian(xlim = c(0, 180), ylim = c(0, 0.02)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Time",
       x = "Travel Time (sec)",
       y = "Density"
      )
TravTime_Sec_HistDen

Investigation of TravelTime_Sec.

TravelTime_Sec values are NA.

summary(AllDays_NewTravelDist$TravelTime_Sec)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
    1.0    25.0    39.0   104.9    72.0 60750.0    6641 
View(select(AllDays_NewTravelDist,
            -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
           ) %>% 
       filter(is.na(TravelTime_Sec) &
                BusDay_EventNum != 1  # TravelTime purposefully not calculated here
             )
    )
# examples of TravelTime_Sec values that are NA. These are NA because the Event_Time & Departure_Time readings are not accurate (i.e., the previous Departure_Time is BEFORE or EQUAL TO the current Event_Time).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 90809 & RowNum_OG <= 90829) | # 90819
                (RowNum_OG >= 90881 & RowNum_OG <= 90901) | # 90891
                (RowNum_OG >= 2597066 & RowNum_OG <= 2597086) | # 2597076
                (RowNum_OG >= 2613305 & RowNum_OG <= 2613325) # 2613315
           ) %>% 
       select(-matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt"))
    )

Investigation of TravelTime_Sec.

TravelTime_Sec values are extremely small.

Investigation of TravelTime_Sec.

TravelTime_Sec values are extremely large.


View(select(AllDays_NewTravelDist,
            -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
           ) %>% 
       filter(!is.na(TravelTime_Sec)
             ) %>% 
       arrange(desc(TravelTime_Sec),
               SpeedAvg_Mph_NewHvrs
              ) %>%
       head(500)
    )

# examples where TravelTime_Sec is large and SpeedAvg_Mph_NewHvrs is small.
View(select(AllDays_NewTravelDist,
            -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
           ) %>% 
       filter((RowNum_OG >= 1007703 & RowNum_OG <= 1007723) | # 1007713
                (RowNum_OG >= 2373564 & RowNum_OG <= 2373584) | # 2373574
                (RowNum_OG >= 864379 & RowNum_OG <= 864399) | # 864389
                (RowNum_OG >= 2570060 & RowNum_OG <= 2570080) # 2570070
           )
    )

Investigation of TravelTime_Sec.

Are large TravelTime_Sec values related to RouteChanges.

str(TTLargeRteChng)
'data.frame':   2809529 obs. of  48 variables:
 $ RowNum_OG                      : int  1 3 4 5 6 7 9 10 11 12 ...
 $ group                          : Factor w/ 5 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ StartStop_ID                   : chr  "NULL--5004572" "5004572--5004573" "5004573--5002210" "5002210--5002209" ...
 $ BusDay_EventNum                : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Bus_ID                         : int  11 11 11 11 11 11 11 11 11 11 ...
 $ Route                          : chr  "S80" "S80" "S80" "S80" ...
 $ RteChange2                     : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 2 2 2 2 ...
 $ RouteAlt                       : Factor w/ 14 levels "1","10","11",..: 1 1 1 1 1 1 6 6 6 6 ...
 $ DirChange2                     : Factor w/ 2 levels "Change","Same": 1 2 2 2 2 2 1 2 2 2 ...
 $ Route_Direction                : Factor w/ 12 levels "","ANTICLKW",..: 6 6 6 6 6 6 6 6 6 6 ...
 $ Stop_Sequence                  : int  7 6 3 2 8 1 2 3 4 2 ...
 $ Start_ID                       : chr  NA "5004572" "5004573" "5002210" ...
 $ Start_Desc                     : chr  NA "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" ...
 $ StopID_Clean                   : chr  "5004572" "5004573" "5002210" "5002209" ...
 $ StopID_Indicator               : Factor w/ 2 levels "ID_Bad","ID_OK": 2 2 2 2 2 2 2 2 2 2 ...
 $ Stop_Desc                      : chr  "BEULAH ST + CHARLES ARRINGTON DR" "WALKER LN + #6363" "WALKER LN + BEULAH ST" "BEULAH ST + CHARLES ARRINGTON DR" ...
 $ Event_Type                     : int  4 4 4 4 3 3 4 4 4 4 ...
 $ Event_Description              : Factor w/ 3 levels "Serviced Stop                                     ",..: 3 3 3 3 1 1 3 3 3 3 ...
 $ Event_Time_Yr                  : int  2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...
 $ Event_Time_Mth                 : int  10 10 10 10 10 10 10 10 10 10 ...
 $ Event_Time_Date                : int  3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Day                 : Ord.factor w/ 7 levels "Sun"<"Mon"<"Tues"<..: 2 2 2 2 2 2 2 2 2 2 ...
 $ Event_Time_Hr                  : int  6 6 6 6 6 6 6 6 6 6 ...
 $ Event_Time_HrGroup             : Ord.factor w/ 8 levels "Group0_2"<"Group3_5"<..: 3 3 3 3 3 3 3 3 3 3 ...
 $ Event_Time_Min                 : int  6 9 10 10 13 14 21 21 23 23 ...
 $ Event_Time                     : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Departure_Time                 : POSIXct, format: "2016-10-03 06:06:47" "2016-10-03 06:09:47" ...
 $ Dwell_Time                     : int  0 0 0 0 0 104 0 0 0 0 ...
 $ Dwell_Time2                    : num  0 0 0 0 0 104 0 0 0 0 ...
 $ Delta_Time                     : int  -177 24 165 25 73 719 74 76 63 69 ...
 $ Latitude                       : num  38.8 38.8 38.8 38.8 38.8 ...
 $ Longitude                      : num  -77.2 -77.2 -77.2 -77.2 -77.2 ...
 $ Heading                        : int  199 97 276 15 119 100 274 104 241 274 ...
 $ Odometer_Distance              : int  43543 45139 46418 50115 51074 51303 55633 56163 56285 57262 ...
 $ Odometer_Distance_Lag1         : int  NA 43543 45139 46418 50115 51074 51303 55633 56163 56285 ...
 $ Odometer_Distance_Mi           : num  8.25 8.55 8.79 9.49 9.67 ...
 $ TravelDistance_Ft              : int  NA 1596 1279 3697 959 229 4330 530 122 977 ...
 $ TravelDistance_Mi              : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_Hvrs         : num  NA 0.15 0.105 0.165 0.832 ...
 $ TravelTime_Sec                 : num  NA 180 37 25 190 29 288 52 76 8 ...
 $ TravelTime_Hr                  : num  NA 0.05 0.01028 0.00694 0.05278 ...
 $ SpeedAvg_Mph                   : num  NA 6.05 23.57 100.83 3.44 ...
 $ TravelDistance_Mi_New          : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_New_Label    : Factor w/ 5 levels "TD_Mi_SS_Mean",..: 4 4 4 4 4 4 4 3 3 4 ...
 $ TravelDistance_Mi_NewHvrs      : num  NA 0.302 0.242 0.7 0.182 ...
 $ TravelDistance_Mi_NewHvrs_Label: Factor w/ 5 levels "TD_Mi_SS_Mean",..: 4 4 4 4 4 5 4 3 3 4 ...
 $ SpeedAvg_Mph_NewHvrs           : num  NA 6.05 23.57 100.83 3.44 ...
 $ TT_Out                         : Factor w/ 2 levels "Normal","Outlier": NA 1 1 1 1 1 1 1 1 1 ...

Investigation of TravelTime_Sec.

If TravelTime_Sec is below the 5th percentile for that StartStop_ID, or if TravelTime_Sec is above the 95th percentile for that StartStop_ID, consider this an outlier. In this case, replace the value with the mean for that StartStop_ID and HourGroup (TT_Sec_SSHG_Mean_F), or if there are not enough values at the HourGroup level, replace it with the mean for that StartStop_ID.

summary(select(NewTravTime,
           -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
          )
   )
   RowNum_OG       group      StartStop_ID       BusDay_EventNum      Bus_ID    
 Min.   :      1   1:559521   Length:2809529     Min.   :   1.0   Min.   :  11  
 1st Qu.: 784722   2:561389   Class :character   1st Qu.: 113.0   1st Qu.:2922  
 Median :1563300   3:567794   Mode  :character   Median : 248.0   Median :6195  
 Mean   :1562504   4:559180                      Mean   : 290.5   Mean   :5382  
 3rd Qu.:2337981   5:561645                      3rd Qu.: 428.0   3rd Qu.:7104  
 Max.   :3119443                                 Max.   :1344.0   Max.   :8105  
                                                                                
    Route            RteChange2         RouteAlt        DirChange2     
 Length:2809529     Change:  23772   2      :1128810   Change:  65126  
 Class :character   Same  :2785757   1      :1065425   Same  :2744403  
 Mode  :character                    3      : 260372                   
                                     4      : 130801                   
                                     5      :  75039                   
                                     6      :  56408                   
                                     (Other):  92674                   
 Route_Direction   Stop_Sequence      Start_ID          Start_Desc       
 SOUTH   :739235   Min.   :  1.00   Length:2809529     Length:2809529    
 NORTH   :735203   1st Qu.: 12.00   Class :character   Class :character  
 WEST    :649706   Median : 24.00   Mode  :character   Mode  :character  
 EAST    :628074   Mean   : 26.83                                        
 LOOP    : 35611   3rd Qu.: 39.00                                        
 CLOCKWIS: 10671   Max.   :104.00                                        
 (Other) : 11029                                                         
 StopID_Clean       StopID_Indicator  Stop_Desc           Event_Type 
 Length:2809529     ID_Bad:  18948   Length:2809529     Min.   :3.0  
 Class :character   ID_OK :2790581   Class :character   1st Qu.:3.0  
 Mode  :character                    Mode  :character   Median :4.0  
                                                        Mean   :3.6  
                                                        3rd Qu.:4.0  
                                                        Max.   :5.0  
                                                                     
                                          Event_Description   Event_Time_Yr 
 Serviced Stop                                     :1127366   Min.   :2016  
 Unknown Stop                                      :   2579   1st Qu.:2016  
 UnServiced Stop                                   :1679584   Median :2016  
                                                              Mean   :2016  
                                                              3rd Qu.:2016  
                                                              Max.   :2016  
                                                                            
 Event_Time_Mth Event_Time_Date Event_Time_Day Event_Time_Hr    Event_Time_HrGroup
 Min.   :10     Min.   :3.000   Sun  :     0   Min.   : 0.00   Group6_8  :611612  
 1st Qu.:10     1st Qu.:4.000   Mon  :559521   1st Qu.: 8.00   Group15_17:560103  
 Median :10     Median :5.000   Tues :561389   Median :13.00   Group18_20:461056  
 Mean   :10     Mean   :5.001   Wed  :567794   Mean   :12.97   Group9_11 :396514  
 3rd Qu.:10     3rd Qu.:6.000   Thurs:559180   3rd Qu.:18.00   Group12_14:353603  
 Max.   :10     Max.   :7.000   Fri  :561645   Max.   :23.00   Group21_23:244522  
                                Sat  :     0                   (Other)   :182119  
 Event_Time_Min    Event_Time                  Departure_Time               
 Min.   : 0.00   Min.   :2016-10-03 00:00:00   Min.   :2016-10-03 00:00:00  
 1st Qu.:14.00   1st Qu.:2016-10-04 08:36:14   1st Qu.:2016-10-04 08:36:20  
 Median :29.00   Median :2016-10-05 13:49:29   Median :2016-10-05 13:49:38  
 Mean   :29.43   Mean   :2016-10-05 13:29:21   Mean   :2016-10-05 13:29:28  
 3rd Qu.:44.00   3rd Qu.:2016-10-06 17:58:06   3rd Qu.:2016-10-06 17:58:13  
 Max.   :59.00   Max.   :2016-10-07 23:59:59   Max.   :2016-10-08 00:12:31  
                                                                            
   Dwell_Time       Dwell_Time2         Delta_Time         Latitude    
 Min.   :   0.00   Min.   :   0.000   Min.   :-5606.0   Min.   : 0.00  
 1st Qu.:   0.00   1st Qu.:   0.000   1st Qu.:   14.0   1st Qu.:38.86  
 Median :   0.00   Median :   0.000   Median :  157.0   Median :38.90  
 Mean   :  12.56   Mean   :   6.359   Mean   :  268.8   Mean   :38.91  
 3rd Qu.:   5.00   3rd Qu.:   4.000   3rd Qu.:  396.0   3rd Qu.:38.96  
 Max.   :6205.00   Max.   :6205.000   Max.   : 9426.0   Max.   :39.19  
                                                                       
   Longitude         Heading      Odometer_Distance  Odometer_Distance_Lag1
 Min.   :-77.45   Min.   :  0.0   Min.   :       0   Min.   :       0      
 1st Qu.:-77.07   1st Qu.: 89.0   1st Qu.:  177595   1st Qu.:  177326      
 Median :-77.02   Median :180.0   Median :  377510   Median :  376934      
 Mean   :-77.02   Mean   :176.9   Mean   :  426254   Mean   :  425713      
 3rd Qu.:-76.97   3rd Qu.:269.0   3rd Qu.:  623667   3rd Qu.:  622879      
 Max.   :  0.00   Max.   :360.0   Max.   :11108034   Max.   :10853226      
                                                     NA's   :6528          
 Odometer_Distance_Mi TravelDistance_Ft TravelDistance_Mi TravelDistance_Mi_Hvrs
 Min.   :   0.00      Min.   :      1   Min.   :  0.0     Min.   : 0.000        
 1st Qu.:  33.64      1st Qu.:    699   1st Qu.:  0.1     1st Qu.: 0.106        
 Median :  71.50      Median :   1044   Median :  0.2     Median : 0.142        
 Mean   :  80.73      Mean   :   1624   Mean   :  0.3     Mean   : 0.201        
 3rd Qu.: 118.12      3rd Qu.:   1518   3rd Qu.:  0.3     3rd Qu.: 0.193        
 Max.   :2103.79      Max.   :1323464   Max.   :250.7     Max.   :24.407        
                      NA's   :322734    NA's   :322734    NA's   :6528          
 TravelTime_Sec    TravelTime_Hr     SpeedAvg_Mph     TravelDistance_Mi_New
 Min.   :    1.0   Min.   : 0.000   Min.   :    0.0   Min.   :  0.000      
 1st Qu.:   25.0   1st Qu.: 0.007   1st Qu.:   10.1   1st Qu.:  0.141      
 Median :   39.0   Median : 0.011   Median :   16.7   Median :  0.199      
 Mean   :  104.9   Mean   : 0.029   Mean   :   26.5   Mean   :  0.298      
 3rd Qu.:   72.0   3rd Qu.: 0.020   3rd Qu.:   31.2   3rd Qu.:  0.276      
 Max.   :60750.0   Max.   :16.875   Max.   :22924.1   Max.   :250.656      
 NA's   :6641      NA's   :6641     NA's   :322762    NA's   :6566         
         TravelDistance_Mi_New_Label TravelDistance_Mi_NewHvrs
 TD_Mi_SS_Mean         :   1425      Min.   : 0.000           
 TD_Mi_SS_Mean_F       :  68790      1st Qu.: 0.142           
 TD_Mi_SSHG_Mean_F     : 235643      Median : 0.199           
 TravelDistance_Mi     :2187829      Mean   : 0.259           
 TravelDistance_Mi_Hvrs: 315842      3rd Qu.: 0.276           
                                     Max.   :36.236           
                                     NA's   :6566             
       TravelDistance_Mi_NewHvrs_Label SpeedAvg_Mph_NewHvrs   TT_Sec_New      
 TD_Mi_SS_Mean         :   1258        Min.   :   0.00      Min.   :    1.00  
 TD_Mi_SS_Mean_F       :  67174        1st Qu.:  10.09      1st Qu.:   25.00  
 TD_Mi_SSHG_Mean_F     : 232871        Median :  16.60      Median :   39.00  
 TravelDistance_Mi     :2122413        Mean   :  24.11      Mean   :   91.31  
 TravelDistance_Mi_Hvrs: 385813        3rd Qu.:  28.83      3rd Qu.:   70.00  
                                       Max.   :8691.73      Max.   :60750.00  
                                       NA's   :6667         NA's   :9218      
           TT_Sec_New_Label     TT_Hr_New     
 TravelTime_Sec    :2503794   Min.   : 0.000  
 TT_Sec_SS_Mean    :    804   1st Qu.: 0.007  
 TT_Sec_SS_Mean_F  :  52426   Median : 0.011  
 TT_Sec_SSHG_Mean_F: 249928   Mean   : 0.025  
 NA's              :   2577   3rd Qu.: 0.019  
                              Max.   :16.875  
                              NA's   :9218    

Investigating TravelTime_Sec.


View(filter(TTLargeRteChng,
            !is.na(TravelTime_Sec) &
              RteChange2 == "Same"
           ) %>% 
       arrange(desc(TravelTime_Sec),
               SpeedAvg_Mph_NewHvrs
              ) %>%
       head(500)
    )


# examples where TravelTime_Sec is small (1 sec) and SpeedAvg_Mph_NewHvrs is large.
View(select(NewTravTime,
            # -matches("(q(2|5|(95)|(98)))|Mean|Med|Cnt")
            -(TD_Mi_q2:TD_Mi_SSHG_Cnt_F),
            -(TT_Hr_q2:TT_Hr_SSHG_Cnt_F)
           ) %>% 
       filter((RowNum_OG >= 2217353 & RowNum_OG <= 2217373) | # 2217363
                (RowNum_OG >= 3090321 & RowNum_OG <= 3090341) | # 3090331
                (RowNum_OG >= 80764 & RowNum_OG <= 80784) | # 80774
                (RowNum_OG >= 33840 & RowNum_OG <= 33860) # 33850
           )
    )






# examples where TravelTime_Sec is large and SpeedAvg_Mph_NewHvrs is small.
View(filter(TTLargeRteChng,
            (RowNum_OG >= 2250290 & RowNum_OG <= 2250310) | # 2250300
              (RowNum_OG >= 867717 & RowNum_OG <= 867737) | # 867727
              (RowNum_OG >= 864379 & RowNum_OG <= 864399) | # 864389
              (RowNum_OG >= 808395 & RowNum_OG <= 808415) # 808405
           )
    )

         
         
# examples where TravelTime_Sec is unusually small (with TravelDistance_Mi values that are large).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 1042228 & RowNum_OG <= 1042248) | # 1042238
                (RowNum_OG >= 53816 & RowNum_OG <= 53836) | # 53826
                (RowNum_OG >= 360571 & RowNum_OG <= 360591) | # 360581
                (RowNum_OG >= 502271 & RowNum_OG <= 502291) # 502281 (can't explian the weird TravelTime_Sec calculation here - it's not even an integer!)
           )
    )

# still trying to explain 502281...on the day of this weirdness, the bus was only in circulation for 4-5 stops (~20 minutes) on that day (Oct 6)
View(filter(AllDays_NewTravelDist,
            Bus_ID == 2711
           )
    )


# exploring large values for TravelTime_Sec
View(filter(AllDays_NewTravelDist,
            TravelTime_Sec == 300
           ) %>% 
       arrange(desc(TravelTime_Sec),
               SpeedAvg_Mph2
              )
    )

# examples where TravelTime_Sec is unusually large (with TravelDistance_Mi values that are small, so SpeedAvg_Mph values are very small).
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 2627459 & RowNum_OG <= 2627479) | # 2627469
                (RowNum_OG >= 2193344 & RowNum_OG <= 2193364) | # 2193354
                (RowNum_OG >= 1644123 & RowNum_OG <= 1644143) | # 1644133
                (RowNum_OG >= 869600 & RowNum_OG <= 869620) # 869610
           )
    )

Investigation of SpeedAvg_Mph2

View(Speed_Pctiles): 90% of SpeedAvg_Mph2 are between ~3mph and ~66mph.


Speed_Ntile <- as.data.frame(AllDays_NewTravelDist$SpeedAvg_Mph2) %>% 
  mutate(Pctile = ntile(AllDays_NewTravelDist$SpeedAvg_Mph2, 100),
         MinR = min_rank(AllDays_NewTravelDist$SpeedAvg_Mph2),
         PctR = percent_rank(AllDays_NewTravelDist$SpeedAvg_Mph2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(Speed_Ntile)[1] <- "SpeedAvg_Mph2"
str(Speed_Ntile)

Speed_Ntile_Rows <- nrow(Speed_Ntile)

View(tail(Speed_Ntile, 500))


Speed_Pctiles <- group_by(Speed_Ntile,
                          PctR_Round
                         ) %>% 
  summarise(
    MinSpeedAtPctile = min(SpeedAvg_Mph2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / Speed_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(Speed_Pctiles)

Investigation of SpeedAvg_Mph2.

Exploring the removal of outlier TravelTime_Sec and TravelDistance_Mi.


summary(select(AllDays_NewTravelDist,
               SpeedAvg_Mph,
               SpeedAvg_Mph2
              )
       )

summary(select(filter(AllDays_NewTravelDist,
                      TravelDistance_Mi > 0.0001893939 & # lowest non-zero percentile
                        TravelDistance_Mi < 1.0812500000 & # 99th percentile
                        TravelTime_Sec > 10.050000 & # 2nd percentile
                        TravelTime_Sec < 293.000000 # 98th percentile
                     ),
               SpeedAvg_Mph,
               SpeedAvg_Mph2
              )
       )

Investigation of SpeedAvg_Mph2.

Histogram of SpeedAvg_Mph2.


Speed_HistDen <- ggplot(filter(AllDays_NewTravelDist,
                               !is.na(SpeedAvg_Mph2)
                              ),
                        aes(x = SpeedAvg_Mph2,
                            y = ..density..
                           )
                       ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  stat_bin(binwidth = 5,
           geom = "text",
           size = 2.5,
           vjust = 1.5,
           aes(label = format(..count.., big.mark = ",")
              ),
          ) +
  # geom_text(aes(label = format(..count.., big.mark = ",")
  #              ),
  #           size = 3,
  #           nudge_y = (..count.. * 0.1)
  #          ) +
  coord_cartesian(xlim = c(0, 70), ylim = c(0, 0.04)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Speed",
       x = "Average Speed (mph)",
       y = "Density"
      )

Speed_HistDen

Investigation of SpeedAvg_Mph2.

Histogram of SpeedAvg_Mph2 after removing outlier TravelTime_Sec and TravelDistance_Mi.


View(TravDistMiNew_Pctiles)
View(TravTimeHr_Pctiles)

SpeedNoOutlier_HistDen <- ggplot(filter(AllDays_NewTravelDist,
                                        !is.na(SpeedAvg_Mph2) &
                                          TravelDistance_Mi_New > 0.077841005 & # 5th percentile
                                          # TravelDistance_Mi_New < 1.0812500000 & # 99th percentile
                                          TravelTime_Sec > 12.100000 # 4th percentile
                                          # TravelTime_Sec < 293.000000 # 98th percentile
                                       ),
                                 aes(x = SpeedAvg_Mph2,
                                     y = ..density..
                                    )
                                ) +
  geom_histogram(binwidth = 5, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  stat_bin(binwidth = 5,
           geom = "text",
           size = 2.5,
           vjust = 1.5,
           aes(label = format(..count.., big.mark = ",")
              ),
          ) +
  # geom_text(aes(label = format(..count.., big.mark = ",")
  #              ),
  #           size = 3,
  #           nudge_y = (..count.. * 0.1)
  #          ) +
  coord_cartesian(xlim = c(0, 70), ylim = c(0, 0.04)
                 ) +
  #  theme(legend.position="none") +
  labs(title = "Variation in Travel Speed",
       subtitle = "(removed low outliers of Travel Distance and Travel Time)",
       x = "Average Speed (mph)",
       y = "Density"
      )

SpeedNoOutlier_HistDen

Investigation of SpeedAvg_Mph2.

New dataset (NoOutliers_TravelDistNTime) when removing outlier low values of TravelDistance_Mi_New and TravelTime_Sec.


View(TravDistMiNew_Pctiles)
View(TravTimeHr_Pctiles)

NoOutliers_TravelDistNTime <- filter(AllDays_NewTravelDist,
                                     TravelDistance_Mi_New > .077841005 & # 5th percentile
                                       # TravelDistance_Mi_New < 1.0812500000 & # 99th percentile
                                       TravelTime_Sec > 12.100000 # 4th percentile
                                       # TravelTime_Sec < 293.000000 # 98th percentile
                                    )

nrow(AllDays_NewTravelDist) - nrow(NoOutliers_TravelDistNTime)

str(NoOutliers_TravelDistNTime)
summary(NoOutliers_TravelDistNTime)

Investigation of SppedAvg_Mph2.

View(Speed_NoOut_Pctiles): Aproximately 90% of SpeedAvg_Mph2 values are between ~4mph and ~56mph.


Speed_NoOut_Ntile <- as.data.frame(NoOutliers_TravelDistNTime$SpeedAvg_Mph2) %>% 
  mutate(Pctile = ntile(NoOutliers_TravelDistNTime$SpeedAvg_Mph2, 100),
         MinR = min_rank(NoOutliers_TravelDistNTime$SpeedAvg_Mph2),
         PctR = percent_rank(NoOutliers_TravelDistNTime$SpeedAvg_Mph2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(Speed_NoOut_Ntile)[1] <- "SpeedAvg_Mph2"
str(Speed_NoOut_Ntile)

Speed_NoOut_Ntile_Rows <- nrow(Speed_NoOut_Ntile)

View(tail(Speed_NoOut_Ntile, 500))


Speed_NoOut_Pctiles <- group_by(Speed_NoOut_Ntile,
                                PctR_Round
                               ) %>% 
  summarise(
    MinSpeedAtPctile = min(SpeedAvg_Mph2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / Speed_NoOut_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(Speed_NoOut_Pctiles)

Investigation of SppedAvg_Mph2.

Exloring odd/impossible values.


# Exploring when SpeedAvg_Mph2 is NA  --  does not occur at all
nrow(filter(NoOutliers_TravelDistNTime,
            is.na(SpeedAvg_Mph2)
           )
    )


# Exploring when SpeedAvg_Mph2 is zero  --  does not occur at all
nrow(filter(NoOutliers_TravelDistNTime,
            SpeedAvg_Mph2 == 0
           )
    )


# examples where SpeedAvg_Mph2 < 3.2848770
View(filter(AllDays_NewTravelDist,
            SpeedAvg_Mph2 > 0 &
              SpeedAvg_Mph2 < 3.2848770
           ) %>% 
       arrange(SpeedAvg_Mph2)
    )

# examples where SpeedAvg_Mph2 < 3.2848770
View(filter(AllDays_NewTravelDist,
            (RowNum_OG >= 485338 & RowNum_OG <= 485358) | # 485348  --  Extreme travel time, Route Change
                (RowNum_OG >= 346952 & RowNum_OG <= 346972) | # 346962  -- Extreme travel time, Route Change 
                (RowNum_OG >= 70494 & RowNum_OG <= 70514) | # 70504  --  Extreme travel time, Route Change
                (RowNum_OG >= 2051846 & RowNum_OG <= 2051866) # 2051856  --  Extreme travel time, Route Change
           )
    )

Investigation of SpeedAvg_Mph2.

Limit the dataset based on SpeedAvg_Mph2.


NoOutliersSpeed <- filter(NoOutliers_TravelDistNTime,
                          between(SpeedAvg_Mph2,
                                  4.069300, # 5th percentile
                                  56.05651 #95th percentile
                                 )
                          )

nrow(NoOutliers_TravelDistNTime) - nrow(NoOutliersSpeed)

summary(NoOutliersSpeed)

TravelTime now looks like it has some odd values on the high end. So let’s look at those.

View(TravTime_NoOut_Pctiles): Virtually all trips should take less than 5 minutes. (The 99th percentile of of TravelTime is approximately 8 minutes.)


TravTime_NoOut_Ntile <- as.data.frame(NoOutliersSpeed$TravelTime_Hr) %>% 
  mutate(Pctile = ntile(NoOutliersSpeed$TravelTime_Hr, 100),
         MinR = min_rank(NoOutliersSpeed$TravelTime_Hr),
         PctR = percent_rank(NoOutliersSpeed$TravelTime_Hr),
         PctR_Round = round(PctR, 2)
        )

colnames(TravTime_NoOut_Ntile)[1] <- "TravelTime_Hr"
str(TravTime_NoOut_Ntile)

TravTime_NoOut_Ntile_Rows <- nrow(TravTime_NoOut_Ntile)

View(tail(TravTime_NoOut_Ntile, 500))


TravTime_NoOut_Pctiles <- group_by(TravTime_NoOut_Ntile,
                                   PctR_Round
                                  ) %>% 
  summarise(
    MinTravTimeHrAtPctile = min(TravelTime_Hr),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / TravTime_NoOut_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile),
         MinTravTimeSecAtPctile = MinTravTimeHrAtPctile * (60 * 60)
        )

View(TravTime_NoOut_Pctiles)

Investigating odd TravelTime_Sec values.

Trips longer than ~8 minutes.


View(filter(NoOutliersSpeed,
            TravelTime_Sec > 491 # min at the 100th percentile
           ) %>% 
       arrange(desc(TravelTime_Sec)
              )
    )

# examples of TravelTime_Sec values that are largest.
View(filter(NoOutliersSpeed,
            (RowNum_OG >= 2071759 & RowNum_OG <= 2071779) | # 2071769  --  results from a route change, and a 3hr+ wait before the new route starts
                (RowNum_OG >= 1473686 & RowNum_OG <= 1473706) | # 1473696  --  results from a route change, and a 3hr wait before the new route starts
                (RowNum_OG >= 1222822 & RowNum_OG <= 1222842) | # 1222832  --  results from a route change, and a 3hr wait before the new route starts
                (RowNum_OG >= 3046089 & RowNum_OG <= 3046109) # 3046099  --  results from a route change, and a 3hr wait before the new route starts
           )
    )


# examples of TravelTime_Sec values that are the smallest of the large.
View(filter(NoOutliersSpeed,
            (RowNum_OG >= 3044689 & RowNum_OG <= 3044709) | # 3044699  --  results from a route change
                (RowNum_OG >= 3022358 & RowNum_OG <= 3022378) | # 3022368  --  results from a route change
                (RowNum_OG >= 2993016 & RowNum_OG <= 2993036) | # 2993026  --  results from a previous route change (change occurred in deleted row)
                (RowNum_OG >= 2683703 & RowNum_OG <= 2683723) # 2683713  --  results from a previous route change (change occurred in deleted row)
           )
    )

Let’s look at the TravelTime_Sec values and route changes (DirChange2).

The 99th percentile of TravelTime_Sec for both, all trips, and just those trips NOT involving route changes (DirChange2 = “Same”), is approximately 5min (300 sec).

Nota Bene: The percentile calculation here is defined slightly different than in most of the above analyses (which get the lowest value in the bin created by 100 ntiles).


summary(select(NoOutliersSpeed,
               TravelTime_Sec
              )
       )

summary(select(filter(NoOutliersSpeed,
                      DirChange2 == "Same"
                     ),
               TravelTime_Sec
              )
       )

summary(select(filter(NoOutliersSpeed,
                      DirChange2 == "Change"
                     ),
               TravelTime_Sec
              )
       )


TravTimeSec_Qtiles_df <- data.frame(PctValue = seq(0, 100, 1),
                                    All = seq(1, 101, 1),
                                    Same = seq(1, 101, 1),
                                    Change = seq(1, 101, 1)
                                   )

TravTimeSec_Qtiles_df[ , 2] <- quantile(select(NoOutliersSpeed,
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

TravTimeSec_Qtiles_df[ , 3] <- quantile(select(filter(NoOutliersSpeed,
                                                      DirChange2 == "Same"
                                                     ),
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

TravTimeSec_Qtiles_df[ , 4] <- quantile(select(filter(NoOutliersSpeed,
                                                      DirChange2 == "Change"
                                                     ),
                                               TravelTime_Sec
                                              ),
                                        probs = seq(0, 1, 0.01),
                                        na.rm = TRUE
                                       )

View(TravTimeSec_Qtiles_df)

Limit the dataset now based on TravelTime_Sec.


UpperLimitTravTime <- filter(NoOutliersSpeed,
                             TravelTime_Sec <= 491 # min at the 100th percentile
                             )

nrow(NoOutliersSpeed) - nrow(UpperLimitTravTime)

str(UpperLimitTravTime)

summary(UpperLimitTravTime)

Investigation of Dwell_Time2 (how long the bus is at a stop).

Differences between Dwell_Time (by WMATA) and Dwell_Time2 (by me) appear to be due to switches in RouteAlt. WMATA calculates Dwell_Time by an unknown process. The WMATA calculation is equal to my calculation, except for the records immedaitely before and after a RouteAlt switch (DirChange2).


View(filter(AllDays_NewOrder,
            Dwell_Time != Dwell_Time2
           )
    )


# Examples where the Dwell_Time and Dwell_Time2 are different
View(filter(AllDays_NewOrder,
            ( (RowNum_OG >= 65 & RowNum_OG <= 85) | # 75
                (RowNum_OG >= 162 & RowNum_OG <= 192) | # 172
                (RowNum_OG >= 431952 & RowNum_OG <= 431972) | # 431962
                (RowNum_OG >= 434595 & RowNum_OG <= 434615) # 434605  --  this record is NOT a route switch, but does has a Sequence switch (Me: should there really be a route switch here?)
            )
           )
    )

Investigation of Dwell_Time2 (how long the bus is at a stop).

First, create some “rank” stats. View(DT2_Pctiles): 95% of Dwell_Time2s are <= 23 seconds…but some weird (e.g., nearly 2 hour Dwell_Time2s exist).


DwellTime2_Ntile <- as.data.frame(AllDays_NewOrder$Dwell_Time2) %>% 
  mutate(Pctile = ntile(AllDays_NewOrder$Dwell_Time2, 100),
         MinR = min_rank(AllDays_NewOrder$Dwell_Time2),
         PctR = percent_rank(AllDays_NewOrder$Dwell_Time2),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DwellTime2_Ntile)[1] <- "Dwell_Time2"
str(DwellTime2_Ntile)

DwellTime2_Ntile_Rows <- nrow(DwellTime2_Ntile)

View(tail(DwellTime2_Ntile, 500))


DwellTime2_Pctiles <- group_by(DwellTime2_Ntile,
                               PctR_Round
                              ) %>% 
  summarise(
    MinDwellAtPctile = min(Dwell_Time2),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DwellTime2_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DwellTime2_Pctiles)

Investigation of Dwell_Time2 (how long the bus is at a stop).

Histogram of Dwell_Time2.


DwellTime2_HistDen <- ggplot(AllDays_NewOrder, aes(x = Dwell_Time2, y = ..density..)) +
  geom_histogram(binwidth = 1, fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(1, 25), ylim = c(0, 0.05)
                 ) +
  xlab("Time a Bus Stays at a Stop (sec)") + 
  ylab("Density") + 
  #  theme(legend.position="none") + 
  ggtitle(expression(atop("Variation in How Long a Bus Stays at a Stop"
                          # ,atop(italic("xxxxx"),"")
                         )
                    )
         )

DwellTime2_HistDen

Investigation of Dwell_Time2 (how long the bus is at a stop).

Looking at some weirdly long Dwell_Time2 values.


View(arrange(AllDays_NewOrder,
             desc(Dwell_Time2)
            )
    )


# examples of extremely large Dwell_Time2s
View(filter(AllDays_NewOrder,
            (RowNum_OG >= 292669 & RowNum_OG <= 292689) | # 292679
                (RowNum_OG >= 531057 & RowNum_OG <= 531077) | # 531067
                (RowNum_OG >= 1388627 & RowNum_OG <= 1388647) | # 1388637
                (RowNum_OG >= 1645711 & RowNum_OG <= 1645731) # 1645721
           )
    )


View(filter(AllDays_NewOrder,
            Dwell_Time2 == 0
           )
    )

Investigation of Delta_Time (how early or late the bus is).

View(DT2_Pctiles): 94% of Delta_Time values are between -236 seconds and 1,259 seconds. Roughly 66% of records are within 5 min late and 5 min early…but some weird (e.g., almost 50 minute late or 40 minute early) Delta_Times exist.

Note that Delta_Time is the difference from the scheduled bus arrival. So if two buses are scheduled to arrive at a destination at 10:00pm and 10:20pm, and if the 10:20pm bus has a Delta_Time of 5 minutes, there are 25 minutes between bus arrivals at the stop.

Also note that based on a comment at https://planitmetro.com/2016/11/16/data-download-metrobus-vehicle-location-data/, the Delta_Time values don’t appear to coincide with published bus schedules (e.g., the X2 departing every 8 minutes during peak hours).


DeltTime_Ntile <- as.data.frame(AllDays_NewOrder$Delta_Time) %>% 
  mutate(Pctile = ntile(AllDays_NewOrder$Delta_Time, 100),
         MinR = min_rank(AllDays_NewOrder$Delta_Time),
         PctR = percent_rank(AllDays_NewOrder$Delta_Time),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DeltTime_Ntile)[1] <- "Delta_Time"
str(DeltTime_Ntile)

DeltTime_Ntile_Rows <- nrow(DeltTime_Ntile)

View(tail(DeltTime_Ntile, 500))


DeltTime_Pctiles <- group_by(DeltTime_Ntile,
                             PctR_Round
                            ) %>% 
  summarise(
    MinDeltTimeAtPctile = min(Delta_Time),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DeltTime_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DeltTime_Pctiles)
DeltTime_Pctiles

# ~66% of rows are between 5 min late and 5 min early
nrow(filter(AllDays_NewOrder,
            Delta_Time >= -300 &
              Delta_Time <= 300
           )
    ) / nrow(AllDays_NewOrder)


# examples of weird large Delta_Times
View(filter(AllDays_NewOrder,
            Delta_Time < -4202 |
              Delta_Time > 1705
           ) %>% 
       arrange(desc(Delta_Time)
              )
    )

Investigation of Delta_Time (how early or late the bus is).

Delta_Time histogram.


DeltTime_HistDen <- ggplot(AllDays_NewOrder, aes(x = (Delta_Time / 60),
                                                 y = ..density..
                                                )
                          ) +
  geom_histogram(binwidth = (5/60), fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_line(stat = "density", colour = "red") +
  coord_cartesian(xlim = c(-5, 5)) +
  xlab("Bus Lateness (min)") + 
  ylab("Density") + 
  #  theme(legend.position="none") + 
  ggtitle(expression(atop("Variation in How Early/Late a Bus Is",
                          atop(italic("(positive values are late arrivals)"),
                               ""
                              )
                         )
                    )
         )

DeltTime_HistDen

Investigation of Delta_Time (how early or late the bus is).

Delta_Time boxplot.


# Count_Values is needed to display the medians on the box plots
Count_Values <- ddply(AllDays_NewOrder,
                      .(Event_Time_HrGroup),
                      summarise,
                      Value_Counts = median(Delta_Time / 60, na.rm = TRUE)
                     )

DeltTime_BoxPlot <- ggplot(AllDays_NewOrder,
                           aes(factor(Event_Time_HrGroup),
                               Delta_Time / 60,
                               fill = factor(Event_Time_HrGroup)
                              )
                          ) + 
  geom_boxplot(outlier.colour="red", notch=TRUE) + 
  # coord_cartesian(ylim = c(-300, 1200)) +
  coord_cartesian(ylim = c(-5, 20)) +
  geom_text(data = Count_Values,
            aes(y = Value_Counts,
                label = format(round(Value_Counts, digits = 1),
                               nsmall = 1
                              )
               ),
            size = 3,
            vjust = -0.5
           ) +
  xlab("Hour Group") + 
  ylab("Bus Lateness (minutes)") + 
  theme(legend.position="none", axis.text.x = element_text(angle=45)) + 
  #theme(legend.position="right", axis.text.x = element_blank()) + 
  ggtitle(expression(atop("How Early/Late is the Bus (by Hour Group)",
                          atop(italic("(positive values are late arrivals)"),
                               ""
                              )
                         )
                    )
         )

DeltTime_BoxPlot

Investigation of Delta_Time (how early or late the bus is).

Exploring “extreme” Delta_Times. First let’s get some “rank” stats.


View(DeltTime_Pctiles)
DeltTime_Pctiles


DeltTimeAbs_Ntile <- as.data.frame(abs(AllDays_NewOrder$Delta_Time)) %>% 
  mutate(Pctile = ntile(abs(AllDays_NewOrder$Delta_Time), 100),
         MinR = min_rank(abs(AllDays_NewOrder$Delta_Time)),
         PctR = percent_rank(abs(AllDays_NewOrder$Delta_Time)),
         PctR_Round = round(PctR, 2)
        ) 

colnames(DeltTimeAbs_Ntile)[1] <- "Delta_Time_Abs"
str(DeltTimeAbs_Ntile)

DeltTimeAbs_Ntile_Rows <- nrow(DeltTimeAbs_Ntile)

View(tail(DeltTimeAbs_Ntile, 500))


DeltTimeAbs_Pctiles <- group_by(DeltTimeAbs_Ntile,
                                PctR_Round
                               ) %>% 
  summarise(
    MinDeltTimeAtPctile = min(Delta_Time_Abs),
    CntsAtPctile = n(),
    PctsAtPctile = CntsAtPctile / DeltTime_Ntile_Rows
  ) %>% 
  mutate(CumSumPAtP = cumsum(PctsAtPctile)
        )

View(DeltTimeAbs_Pctiles)
DeltTimeAbs_Pctiles

Investigation of Delta_Time (how early or late the bus is).

Exploring “extreme” Delta_Times. Then let’s calculate the percentage of buses that are 10 minutes (or more) late/early.


HrGroup_DeltaTime_All <- group_by(AllDays_NewOrder,
                                  Event_Time_HrGroup
                                 ) %>% 
  summarise(EventAll_Cnt = n()
           )

str(HrGroup_DeltaTime_All)
View(HrGroup_DeltaTime_All)


HrGroup_DeltaTime_Above10Min <- filter(AllDays_NewOrder,
                                       abs(Delta_Time) >= 600
                                      ) %>% 
  group_by(Event_Time_HrGroup) %>% 
  summarise(EventAbove10_Cnt = n()
           )

str(HrGroup_DeltaTime_Above10Min)
View(HrGroup_DeltaTime_Above10Min)


HrGroup_DeltaTimeCompare <- inner_join(HrGroup_DeltaTime_Above10Min,
                                       HrGroup_DeltaTime_All,
                                       by = c("Event_Time_HrGroup" = "Event_Time_HrGroup")
                                      ) %>% 
  mutate(PctEventsAbove10 = EventAbove10_Cnt / EventAll_Cnt)

View(HrGroup_DeltaTimeCompare)

Investigation of Delta_Time (how early or late the bus is).

Quickly plot these “extreme” Delta_Times.


DeltTime_Above10_Cols <- ggplot(HrGroup_DeltaTimeCompare,
                                aes(factor(Event_Time_HrGroup),
                                    PctEventsAbove10
                                   )
                               ) +
  geom_col(fill = "lightblue", colour = "grey60", size = 0.2) +
  geom_text(aes(label = format(round(PctEventsAbove10, digits = 2),
                               nsmall = 2
                              )
               ),
            size = 3,
            nudge_y = (HrGroup_DeltaTimeCompare$PctEventsAbove10 * -0.1)
           ) +
  # coord_cartesian(xlim = c(-5, 5)) +
  xlab("Hour Group") + 
  ylab("Percent of All Bus Arrivals") +
  theme(legend.position="none", axis.text.x = element_text(angle=45)) +
  ggtitle(expression(atop("When is a Bus 10+ Minutes Late/Early"
                          # ,atop(italic("positive values are late arrivals"),
                          #      ""
                          #     )
                         )
                    )
         )

DeltTime_Above10_Cols

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Correlation.


DwellTDeltaT_Corr <- as.matrix(cor(x = AllDays_NewOrder$Dwell_Time2,
                                   y = AllDays_NewOrder$Delta_Time,
                                   use = "pairwise"
                                  )
                               )

DwellTDeltaT_Corr

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Next, let’s get a sample of data for plotting. Let’s do this for the full dataset (AllDays_NewOrder).


AllDays_NewOrder_10PctSamp <- sample_frac(AllDays_NewOrder, 0.1) %>% 
  select(Delta_Time,
         Dwell_Time2
        ) %>% 
  mutate(DataSet = "AllData")

str(AllDays_NewOrder_10PctSamp)

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Let’s also get a sample of data for plotting, but with a datset that removes outliers.


View(DeltTime_Pctiles)
View(DwellTime2_Pctiles)

AllDays_NewOrder_NoExtremes_10PctSamp <- filter(AllDays_NewOrder,
                                                between(Delta_Time, -402, 1705) & # removes about 2% of Delta_Time values
                                                  between(Dwell_Time2, 1, 63)  # removes about 2% of Dwell_Time2 values
                                               ) %>% 
  sample_frac(0.1) %>% 
  select(Delta_Time,
         Dwell_Time2
        ) %>% 
  mutate(DataSet = "OutliersRemoved")

str(AllDays_NewOrder_NoExtremes_10PctSamp)

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from the dataset that does not remove outliers.


DwellTDeltaT_Scatter <- ggplot(AllDays_NewOrder_10PctSamp,
                               aes(Dwell_Time2, Delta_Time)
                              ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "red") +
  # xlab("Time at Stop (sec)") + 
  # ylab("Lateness (sec)") +
  annotate(label = lm_eqn(df = AllDays_NewOrder_10PctSamp,
                          y = AllDays_NewOrder_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_10PctSamp$Dwell_Time2
                         ),
           x = 2200,
           y = 600,
           geom = "text",
           size = 3,
           colour = "red",
           parse = TRUE
          ) +
  labs(title = "Lateness vs Time at Stop",
       subtitle = "(no outliers removed)",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
  #                         ,atop(italic("(no outliers removed)"),
  #                               ""
  #                              )
  #                        )
  #                   )
  #        )
# +
#   geom_jitter()

DwellTDeltaT_Scatter

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from the dataset that does remove outliers.


DwellTDeltaT_Scatter_NoExtremes <- ggplot(AllDays_NewOrder_NoExtremes_10PctSamp,
                                          aes(Dwell_Time2, Delta_Time)
                                         ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  geom_smooth(method = "lm", colour = "blue") +
  # xlab("Time at Stop (sec)") + 
  # ylab("Lateness (sec)") +
  annotate(label = lm_eqn(df = AllDays_NewOrder_NoExtremes_10PctSamp,
                          y = AllDays_NewOrder_NoExtremes_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_NoExtremes_10PctSamp$Dwell_Time2
                         ),
           x = 50,
           y = -475,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  labs(title = "Lateness vs Time at Stop",
       subtitle = "(2% of outliers removed)",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
  #                         ,atop(italic("(2% of outliers removed)"),
  #                               ""
  #                              )
  #                        )
  #                   )
  #        )
# +
#   geom_jitter()

DwellTDeltaT_Scatter_NoExtremes

Quick investigation on the relationship between Dwell_Time2 (the time a bus is at a stop) and Delta_Time (how early/late the bus is).

Plotting the data from both datasets together.


CombinedData <- rbind(AllDays_NewOrder_10PctSamp,
                      AllDays_NewOrder_NoExtremes_10PctSamp
                     )

CombinedData$DataSet <- factor(CombinedData$DataSet)

str(CombinedData)


DwellTDeltaT_Scatter_Combined <- ggplot(CombinedData,
                                        aes(x = Dwell_Time2,
                                            y = Delta_Time,
                                            colour = DataSet
                                           )
                                       ) +
  geom_point(shape = 1, alpha = 0.5) +
  scale_shape(solid = FALSE) +
  coord_cartesian(xlim = c(0, 500), ylim = c(-1000, 2000)
                 ) +
  geom_smooth(data = filter(CombinedData,
                            DataSet == "AllData"
                           ),
              method = "lm",
              colour = "red"
             ) +
  geom_smooth(data = filter(CombinedData,
                            DataSet == "OutliersRemoved"
                           ),
              method = "lm",
              colour = "blue"
             ) +
  # facet_wrap( ~ DataSet, ncol = 2) +
  annotate(label = lm_eqn(df = AllDays_NewOrder_10PctSamp,
                          y = AllDays_NewOrder_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_10PctSamp$Dwell_Time2
                         ),
           x = 300,
           y = -600,
           geom = "text",
           size = 3,
           colour = "red",
           parse = TRUE
          ) +
  annotate(label = lm_eqn(df = AllDays_NewOrder_NoExtremes_10PctSamp,
                          y = AllDays_NewOrder_NoExtremes_10PctSamp$Delta_Time,
                          x = AllDays_NewOrder_NoExtremes_10PctSamp$Dwell_Time2
                         ),
           x = 300,
           y = -800,
           geom = "text",
           size = 3,
           colour = "blue",
           parse = TRUE
          ) +
  theme(legend.position = "bottom") +
  labs(title = "Lateness vs Time at Stop",
       x = "Time at Stop (sec)",
       y = "Lateness (sec)"
      )
  # ggtitle(expression(atop("Lateness vs Time at Stop"
                          # ,atop(italic("2% of outliers removed"),
                          #       ""
                          #      )
         #                 )
         #            )
         # )
# +
#   geom_jitter()

DwellTDeltaT_Scatter_Combined

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Cmd+Option+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Cmd+Shift+K to preview the HTML file).

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayBmb3IgV01BVEEgTWV0cm9idXMgRGF0YSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2sgZm9yIGFuYWx5c2lzIHVzaW5nIGRhdGEgb24gdGhlIERDIEJ1cyBTeXN0ZW0gKFdNQVRBIE1ldHJvYnVzKS4gIFRoZSBkYXRhIHdlcmUgb2J0YWluZWQgaGVyZToKCmh0dHBzOi8vcGxhbml0bWV0cm8uY29tLzIwMTYvMTEvMTYvZGF0YS1kb3dubG9hZC1tZXRyb2J1cy12ZWhpY2xlLWxvY2F0aW9uLWRhdGEvCgpDb250cm9sICsgQWx0ICsgU2hpZnQgKyBtID0gcmVuYW1lIGluIHNjb3BlCgpMb2FkIHRoZSBwYWNrYWdlcyB0byBiZSB1c2VkLgpgYGB7ciBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KCmxpYnJhcnkoImpzb25saXRlIikKbGlicmFyeSgidGlkeXIiKQpsaWJyYXJ5KCJwbHlyIikKbGlicmFyeSgiZHBseXIiKQpsaWJyYXJ5KCJtYWdyaXR0ciIpCmxpYnJhcnkoInN0cmluZ3IiKQpsaWJyYXJ5KCJkYXRhLnRhYmxlIikKbGlicmFyeSgibHVicmlkYXRlIikKbGlicmFyeSgiZ2Vvc3BoZXJlIikKbGlicmFyeSgiZ2dwbG90MiIpCmxpYnJhcnkoImdndmlzIikKbGlicmFyeSgicmJva2VoIikKCmBgYAoKCkdldCB0aGUgQnVzIGRhdGEuCgpGaXJzdCBsZXQncyBjaGVjayB0aGUgd29ya2luZyBkaXJlY3RvcnkuCmBgYHtyfQoKZ2V0d2QoKQoKYGBgCgoKVGhlbiwgYWN0dWFsbHkgZ2V0IHRoZSBkYXRhLgpgYGB7ciBlY2hvID0gRkFMU0V9CgpzZXR3ZCgiL1VzZXJzL21kdHVyc2UvRGVza3RvcC9BbmFseXRpY3MvRENNZXRyb0J1cy9CdXMgQVZMIE9jdCAyMDE2IikKCmZvciAoaSBpbiAzOjcpewogIGFzc2lnbihwYXN0ZTAoIk9jdDAiLCBpLCAiUmF3IiksCiAgICAgICAgIHJlYWQuZGVsaW0ocGFzdGUwKCIyMDE2MTAwIiwgaSwgIk1ldHJvYnVzQVZMLnR4dCIpLAogICAgICAgICAgICAgICAgICAgIHNlcCA9ICJcdCIsCiAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICBuYS5zdHJpbmdzID0gTlVMTAogICAgICAgICAgICAgICAgICAgKQogICAgICAgICkKICAKICBtZXNzYWdlKCJPY3QwIiwgaSwgIlJhdyIpCiAKICBzdHIoZ2V0KHBhc3RlMCgiT2N0MCIsIGksICJSYXciKQogICAgICAgICApCiAgICAgKQogIH0KCmBgYAoKClB1dCB0aGUgZGFpbHkgZGF0YSB0b2dldGhlci4KYGBge3J9CgpBbGxEYXlzIDwtIGJpbmRfcm93cyhsaXN0KE9jdDAzUmF3LCBPY3QwNFJhdywgT2N0MDVSYXcsIE9jdDA2UmF3LCBPY3QwN1JhdyksCiAgICAgICAgICAgICAgICAgICAgIC5pZCA9IGMoImdyb3VwIikKICAgICAgICAgICAgICAgICAgICApCiMgZGltKEFsbERheXMpCnN0cihBbGxEYXlzKQoKYGBgCgoKRGVsZXRpbmcgb2xkIGRhdGEgZnJhbWVzLgpgYGB7cn0KCmZvciAoaSBpbiAzOjcpewogIHJtKGxpc3QgPSBscyhwYXR0ZXJuID0gcGFzdGUwKCJPY3QwIiwgaSwgIlJhdyIpCiAgICAgICAgICAgICAgKQogICAgKQogIAogIG1lc3NhZ2UoIkRlbGV0aW5nIE9jdDAiLCBpLCAiUmF3IikKICB9CgpgYGAKCgpVcGRhdGluZyB2YXJpYWJsZSB0eXBlcy4KClRoZW4sIHNvcnRpbmcgdGhlIGRhdGEgYW5kIGFkZGluZyBhIFJvd051bWJlciAodG8gYmUgdXNlZCBmb3IgaWRlbnRpZnlpbmcgcm93cyBsYXRlciBpbiB0aGUgYW5hbHlzZXMuKQpgYGB7cn0KCnJtKGkpCgoKQWxsRGF5cyRncm91cCA8LSBmYWN0b3IoQWxsRGF5cyRncm91cCkKQWxsRGF5cyRSb3V0ZV9EaXJlY3Rpb24gPC0gZmFjdG9yKEFsbERheXMkUm91dGVfRGlyZWN0aW9uKQpBbGxEYXlzJEV2ZW50X1RpbWUgPC0gYXMuUE9TSVhjdChBbGxEYXlzJEV2ZW50X1RpbWUsIGZvcm1hdCA9ICIlbS0lZC0leSAlSTolTTolUyAlcCIpCkFsbERheXMkRGVwYXJ0dXJlX1RpbWUgPC0gYXMuUE9TSVhjdChBbGxEYXlzJERlcGFydHVyZV9UaW1lLCBmb3JtYXQgPSAiJW0tJWQtJXkgJUk6JU06JVMgJXAiKQoKc3RyKEFsbERheXMpCgoKQWxsRGF5c19Tb3J0ZWQgPC0gYXJyYW5nZShBbGxEYXlzLAogICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c19JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lCiAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoUm93TnVtX09HID0gcm93X251bWJlcigpICMgdGhpcyBpcyB1c2VmdWwgaW4gaWRlbnRpZnkgdGhlIHJvdyBsYXRlciBvbgogICAgICAgICkKCnJtKEFsbERheXMpCnN0cihBbGxEYXlzX1NvcnRlZCkKCiMgVmlldyhoZWFkKEFsbERheXNfU29ydGVkLCAxMDApKQoKYGBgCgoKSW5zcGVjdGluZyB0aGUgdmFsdWVzIG9mIFN0b3BfSUQsIGFuZCBmaW5kaW5nIHRoYXQgaXQgY2FuIHRha2UgdGhlIHZhbHVlcyAiIiAoYmxhbmspIGFuZCAiTlVMTCIuCmBgYHtyfQoKVmlldyhncm91cF9ieShBbGxEYXlzX1NvcnRlZCwKICAgICAgICAgICAgICBTdG9wX0lECiAgICAgICAgICAgICApICU+JSAKICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgQ250ID0gbigpCiAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShTdG9wX0lEKQogICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19Tb3J0ZWQsCiAgICAgICAgICAgIGlzLm5hKFN0b3BfSUQpIHwKICAgICAgICAgICAgICBTdG9wX0lEID09ICIiIHwKICAgICAgICAgICAgICBTdG9wX0lEID09ICJOVUxMIgogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShTdG9wX0Rlc2MpCiAgICApCgpgYGAKCgpDcmVhdGluZyBhIHRhYmxlIG9mIGRpc3RpbmN0IFN0b3BfRGVzYyB2YWx1ZXMgd2hlbiBTdG9wX0lEIGlzICIiIChibGFuaykgb3IgIk5VTEwiLgpgYGB7cn0KClN0b3BJRF9OZXcgPC0gZmlsdGVyKEFsbERheXNfU29ydGVkLAogICAgICAgICAgICAgICAgICAgICBpcy5uYShTdG9wX0lEKSB8CiAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9JRCA9PSAiIiB8CiAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9JRCA9PSAiTlVMTCIKICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzZWxlY3QoU3RvcF9JRCwgU3RvcF9EZXNjKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUgCiAgYXJyYW5nZShTdG9wX0lELCBTdG9wX0Rlc2MpICU+JSAKICBtdXRhdGUoU3RvcElEX05ldyA9IDE6bnJvdyguKQogICAgICAgICkKClZpZXcoU3RvcElEX05ldykKCmBgYAoKCkNyZWF0aW5nIGEgZnVsbCB1cGRhdGVkIHRhYmxlIGJ5IGZpbGxpbmcgaW4gU3RvcElEX05ldyBmb3Igd2hlbiBTdG9wX0lEIGlzICIiIChibGFuaykgb3IgTlVMTC4KYGBge3J9CgpBbGxEYXlzX1N0b3BJRE5ldyA8LSBsZWZ0X2pvaW4oQWxsRGF5c19Tb3J0ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoU3RvcElEX05ldywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wX0Rlc2MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcElEX05ldwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiU3RvcF9EZXNjIiA9ICJTdG9wX0Rlc2MiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoU3RvcElEX0NsZWFuID0gaWZlbHNlKGlzLm5hKFN0b3BJRF9OZXcpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BJRF9OZXcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgU3RvcElEX0luZGljYXRvciA9IGZhY3RvcihpZmVsc2UoaXMubmEoU3RvcElEX05ldyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJRF9PSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJRF9CYWQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICkKCnJtKFN0b3BJRF9OZXcpCnJtKEFsbERheXNfU29ydGVkKQpzdHIoQWxsRGF5c19TdG9wSUROZXcpCgojIFZpZXcodGFpbChBbGxEYXlzX1N0b3BJRE5ldywgNTAwKSkKIyBWaWV3KGZpbHRlcihBbGxEYXlzX1N0b3BJRE5ldywKIyAgICAgICAgICAgICBTdG9wX0Rlc2MgPT0gIk1FVFJPV0FZIEFOTk5PVUNFTU5UIENPUlIiCiMgICAgICAgICAgICApCiMgICAgICkKCmBgYAoKCgpMYXQgTG9uZyBzdGF0cyBmb3IgcHVsbGluZyBpbiBaaXAgY29kZXMgbGF0ZXIuCmBgYHtyfQoKTExfU3RhdHMgPC0gZ3JvdXBfYnkoQWxsRGF5c19TdG9wSUROZXcsCiAgICAgICAgICAgICAgICAgICAgIFN0b3BJRF9DbGVhbgogICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZShMYXRfTWVhbiA9IG1lYW4oTGF0aXR1ZGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIExhdF9NZWQgPSBtZWRpYW4oTGF0aXR1ZGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIExuZ19NZWFuID0gbWVhbihMb25naXR1ZGUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIExuZ19NZWQgPSBtZWRpYW4oTG9uZ2l0dWRlLCBuYS5ybSA9IFRSVUUpCiAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKExhdF9NZWFMZXNzTWVkID0gTGF0X01lYW4gLSBMYXRfTWVkLAogICAgICAgICBMbmdfTWVhTGVzc01lZCA9IExuZ19NZWFuIC0gTG5nX01lZCwKICAgICAgICAgUm93TnVtID0gcm93X251bWJlcigpCiAgICAgICAgKQoKc3RyKExMX1N0YXRzKQpzdW1tYXJ5KExMX1N0YXRzKQoKVmlldyhoZWFkKGFycmFuZ2UoTExfU3RhdHMsCiAgICAgICAgICAgICAgICAgIExhdF9NZWFMZXNzTWVkCiAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgIDUwMAogICAgICAgICApCiAgICApCgpWaWV3KGhlYWQoYXJyYW5nZShMTF9TdGF0cywKICAgICAgICAgICAgICAgICAgZGVzYyhMYXRfTWVhTGVzc01lZCkKICAgICAgICAgICAgICAgICApLAogICAgICAgICAgNTAwCiAgICAgICAgICkKICAgICkKClZpZXcoaGVhZChhcnJhbmdlKExMX1N0YXRzLAogICAgICAgICAgICAgICAgICBMbmdfTWVhTGVzc01lZAogICAgICAgICAgICAgICAgICksCiAgICAgICAgICA1MDAKICAgICAgICAgKQogICAgKQoKVmlldyhoZWFkKGFycmFuZ2UoTExfU3RhdHMsCiAgICAgICAgICAgICAgICAgIGRlc2MoTG5nX01lYUxlc3NNZWQpCiAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgIDUwMAogICAgICAgICApCiAgICApCgpgYGAKCgpQdWxsaW5nIGluIFppcCBDb2RlIGRhdGEuCmBgYHtyfQoKIyBMTF9TdGF0c19UZXN0IDwtIGRhdGEudGFibGUoaGVhZChMTF9TdGF0cywgMTAwKSkKIyBzZXRrZXkoTExfU3RhdHNfVGVzdCwgUm93TnVtKQojIHN0cihMTF9TdGF0c19UZXN0KQojIAojIFZpZXcoTExfU3RhdHNfVGVzdCkKCiMgVVJMIEVYQU1QTEUKIyBodHRwOi8vYXBpLmdlb25hbWVzLm9yZy9maW5kTmVhcmJ5UG9zdGFsQ29kZXNKU09OP2xhdD0zOC44OTU2MCZsbmc9LTc2Ljk0ODczJnJhZGl1cz0wJnVzZXJuYW1lPXN1cGVybWRhdAoKdXJsXzEgPC0gImh0dHA6Ly9hcGkuZ2VvbmFtZXMub3JnL2ZpbmROZWFyYnlQb3N0YWxDb2Rlc0pTT04/bGF0PSIKdXJsXzIgPC0gIiZsbmc9Igp1cmxfMyA8LSAiJnJhZGl1cz0wJnVzZXJuYW1lPSIKdXNlcm5hbWUgPC0gInN1cGVybWRhdCIKCgpWaWV3KGZpbHRlcihMTF9TdGF0cywKICAgICAgICAgICAgUm93TnVtID09ICgxOTUwICsgMTAwMikKICAgICAgICAgICApCiAgICApCgojIyMjIyBTdG9yZSBldmVyeXRoaW5nIGluIG11bHRpcGxlIGxpc3RzCgojIHBhZ2VzIDwtIGxpc3QoKQojIHBhZ2VzMiA8LSBsaXN0KCkKIyBwYWdlczMgPC0gbGlzdCgpCiMgcGFnZXM0IDwtIGxpc3QoKQojIHBhZ2VzNSA8LSBsaXN0KCkKcGFnZXM2IDwtIGxpc3QoKQojIHBhZ2VzNyA8LSBsaXN0KCkKIyBwYWdlczggPC0gbGlzdCgpCiMgcGFnZXM5IDwtIGxpc3QoKQojIHBhZ2VzMTAgPC0gbGlzdCgpCiMgcGFnZXMxMSA8LSBsaXN0KCkKCiMgbWF4X3Jvd19wZXJfaHIgPC0gMTAwMAojIG5lZWQgdG8gZ3JvdXAgaW4gYnVuY2hlcyBhcyBodHRwOi8vYXBpLmdlb25hbWVzLm9yZyBsaW1pdHMgcHVsbHMgdG8gMjAwMCBwZXIgaG91cgoKCgpzeXN0ZW0udGltZSgKIyAgIGZvcihqIGluIDA6NSl7CiMgICBmb3IoayBpbiAoKG1heF9yb3dfcGVyX2hyKmopICsgMSk6KG1heF9yb3dfcGVyX2hyKihqKzEpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgKXsKIyAgICAgCiMgICB9CiMgfQpmb3IoIyBpIGluIDE6bnJvdyhMTF9TdGF0cykKICAgICMgaSBpbiAxOjE5NTAKICAgIGkgaW4gMToxMDAwICMgMjA1MSAjMzkwMAogICAgIyBpIGluIDM5MDE6NTg1MAogICAgIyBpIGluIDU4NTE6NzgwMAogICAgIyBpIGluIDc4MDE6OTc1MAogICAgIyBpIGluIDk3NTE6bnJvdyhMTF9TdGF0cykKICAgKXsKICBsYXQgPC0gZmlsdGVyKExMX1N0YXRzLAogICAgICAgICAgICAgICAgUm93TnVtID09IChpICsgMTk1MCArIDEwMDAgKyAxMDAwICsgMTAwMCArIDEwMDApCiAgICAgICAgICAgICAgICkgJT4lCiAgICBzZWxlY3QoTGF0X01lZCkKICAjIGxhdCA8LSBMTF9TdGF0c19UZXN0W2ksIExhdF9NZWRdCiAgCiAgbG5nIDwtIGZpbHRlcihMTF9TdGF0cywKICAgICAgICAgICAgICAgIFJvd051bSA9PSAoaSArIDE5NTAgKyAxMDAwICsgMTAwMCArIDEwMDAgKyAxMDAwKQogICAgICAgICAgICAgICApICU+JQogICAgc2VsZWN0KExuZ19NZWQpCiAgIyBsbmcgPC0gTExfU3RhdHNfVGVzdFtpLCBMbmdfTWVkXQogIAogICMgQVBJRGF0YSA8LSBmcm9tSlNPTihwYXN0ZTAodXJsXzEsCiAgIyBBUElEYXRhMiA8LSBmcm9tSlNPTihwYXN0ZTAodXJsXzEsCiAgIyBBUElEYXRhMyA8LSBmcm9tSlNPTihwYXN0ZTAodXJsXzEsCiAgIyBBUElEYXRhNCA8LSBmcm9tSlNPTihwYXN0ZTAodXJsXzEsCiAgIyBBUElEYXRhNSA8LSBmcm9tSlNPTihwYXN0ZTAodXJsXzEsCiAgQVBJRGF0YTYgPC0gZnJvbUpTT04ocGFzdGUwKHVybF8xLAogICMgQVBJRGF0YTcgPC0gZnJvbUpTT04ocGFzdGUwKHVybF8xLAogICMgQVBJRGF0YTggPC0gZnJvbUpTT04ocGFzdGUwKHVybF8xLAogICMgQVBJRGF0YTkgPC0gZnJvbUpTT04ocGFzdGUwKHVybF8xLAogICMgQVBJRGF0YTEwIDwtIGZyb21KU09OKHBhc3RlMCh1cmxfMSwKICAjIEFQSURhdGExMSA8LSBmcm9tSlNPTihwYXN0ZTAodXJsXzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVybF8yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxuZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmxfMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VybmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgIGZsYXR0ZW4gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICkKICAKICBtZXNzYWdlKCJSZXRyaWV2aW5nIFppcCBDb2RlICIsIChpICsgMTk1MCArIDEwMDAgKyAxMDAwICsgMTAwMCArIDEwMDApCiAgICAgICAgICkKICAKICAjIHBhZ2VzW1tpXV0gPC0gQVBJRGF0YSRwb3N0YWxDb2RlcwogICMgcGFnZXMyW1tpXV0gPC0gQVBJRGF0YTIkcG9zdGFsQ29kZXMKICAjIHBhZ2VzM1tbaV1dIDwtIEFQSURhdGEzJHBvc3RhbENvZGVzCiAgIyBwYWdlczRbW2ldXSA8LSBBUElEYXRhNCRwb3N0YWxDb2RlcwogICMgcGFnZXM1W1tpXV0gPC0gQVBJRGF0YTUkcG9zdGFsQ29kZXMKICBwYWdlczZbW2ldXSA8LSBBUElEYXRhNiRwb3N0YWxDb2RlcwogICMgcGFnZXM3W1tpXV0gPC0gQVBJRGF0YTckcG9zdGFsQ29kZXMKICAjIHBhZ2VzOFtbaV1dIDwtIEFQSURhdGE4JHBvc3RhbENvZGVzCiAgIyBwYWdlczlbW2ldXSA8LSBBUElEYXRhOSRwb3N0YWxDb2RlcwogICMgcGFnZXMxMFtbaV1dIDwtIEFQSURhdGExMCRwb3N0YWxDb2RlcwogICMgcGFnZXMxMVtbaV1dIDwtIEFQSURhdGExMSRwb3N0YWxDb2RlcwogIAogICMgU3lzLnNsZWVwKDM5MDApCn0KKQojIGNsYXNzKEFQSURhdGEyKQojIGNsYXNzKEFQSURhdGEyJHBvc3RhbENvZGVzKQojIHN0cihBUElEYXRhMikKIyBoZWFkKEFQSURhdGEkcG9zdGFsQ29kZXMkcG9zdGFsQ29kZSkKIyBoZWFkKEFQSURhdGEpCiMgCmNsYXNzKHBhZ2VzMikKIyBzdHIocGFnZXMyKQojIG5yb3cocGFnZXMpCiMgbmNvbChwYWdlcykKcGFnZXMyW1sxMTk5XV0KcGFnZXMyW1syMDUxXV0KaGVhZChwYWdlczJbWzFdXSwgMykKdGFpbChwYWdlcywgMikKcGFnZXMkZGF0YS5mcmFtZSRBUElEYXRhJHBvc3RhbENvZGVzJHBvc3RhbENvZGUKcGFnZXMkQVBJRGF0YSRwb3N0YWxDb2RlcyRwb3N0YWxDb2RlCiMgaGVhZChwYWdlc1tbMV1dLCAyKQojIAojIHBhZ2VzW1sxXV0kUHJvZHVjdHMkTGlzdAojIAojIHBhZ2VzW1sxXV0kUHJvZHVjdHMkTGlzdCRJZAojIHBhZ2VzW1sxXV0kUHJvZHVjdHMkTGlzdCROYW1lCiMgCiMgcGFnZXNbWzJdXSRQcm9kdWN0cyRMaXN0JElkCiMgcGFnZXNbWzJdXSRQcm9kdWN0cyRMaXN0JE5hbWUKCgojIyMjIyBDb21iaW5lIHRoZSBsaXN0cyBpbnRvIG9uZQoKIyBBUElEYXRhX0FsbCA8LSByYmluZC5maWxsKHBhZ2VzKQojIFppcHMgPC0gcmJpbmQucGFnZXMocGFnZXMpCiMgWmlwczIgPC0gcmJpbmQucGFnZXMocGFnZXMyW3NhcHBseShwYWdlczIsIGxlbmd0aCkgPiAwXSkKIyBaaXBzMyA8LSByYmluZC5wYWdlcyhwYWdlczNbc2FwcGx5KHBhZ2VzMywgbGVuZ3RoKSA+IDBdKQojIFppcHM0IDwtIHJiaW5kLnBhZ2VzKHBhZ2VzNFtzYXBwbHkocGFnZXM0LCBsZW5ndGgpID4gMF0pCiMgWmlwczUgPC0gcmJpbmQucGFnZXMocGFnZXM1W3NhcHBseShwYWdlczUsIGxlbmd0aCkgPiAwXSkKWmlwczYgPC0gcmJpbmQucGFnZXMocGFnZXM2W3NhcHBseShwYWdlczYsIGxlbmd0aCkgPiAwXSkKIyBaaXBzNyA8LSByYmluZC5wYWdlcyhwYWdlczdbc2FwcGx5KHBhZ2VzNywgbGVuZ3RoKSA+IDBdKQojIFppcHM4IDwtIHJiaW5kLnBhZ2VzKHBhZ2VzOFtzYXBwbHkocGFnZXM4LCBsZW5ndGgpID4gMF0pCiMgWmlwczkgPC0gcmJpbmQucGFnZXMocGFnZXM5W3NhcHBseShwYWdlczksIGxlbmd0aCkgPiAwXSkKIyBaaXBzMTAgPC0gcmJpbmQucGFnZXMocGFnZXMxMFtzYXBwbHkocGFnZXMxMCwgbGVuZ3RoKSA+IDBdKQojIFppcHMxMSA8LSByYmluZC5wYWdlcyhwYWdlczExW3NhcHBseShwYWdlczExLCBsZW5ndGgpID4gMF0pCgoKcGFnZXNbc2FwcGx5KHBhZ2VzLCBsZW5ndGgpIDw9IDBdCnBhZ2VzMltzYXBwbHkocGFnZXMyLCBsZW5ndGgpIDw9IDBdCgpzdHIoWmlwczMpCnRhaWwoWmlwcykKVmlldyhaaXBzMikKIyBBUElEYXRhX0FsbDIgPC0gcmJpbmQucGFnZXMocGFnZXMyKQojIGJpbmRfcm93cyhwYWdlcykKIyBBUElEYXRhX0FsbCA8LSByYmluZC5wYWdlcyhjKHBhZ2VzW1sxXV0sCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlc1tbMl1dLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZXNbWzNdXQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpjbGFzcyhBUElEYXRhX0FsbCkKIyBzdHIoQVBJRGF0YV9BbGwpCm5yb3coQVBJRGF0YV9BbGwpCm5jb2woQVBJRGF0YV9BbGwpCmhlYWQoQVBJRGF0YV9BbGwsIDMpCnRhaWwoQVBJRGF0YV9BbGwsIDMpCiMgVmlldyhBUElEYXRhX0FsbCkKVmlldyhoZWFkKEFQSURhdGFfQWxsLCAzKQogICAgKQoKc3RyKFppcHMyKQoKTExfU3RhdHNfVGVzdCA8LSBtdXRhdGUoTExfU3RhdHMsCiAgICAgICAgICAgICAgICAgICAgICAgIFVuaXF1ZUxhdExuZyA9IHBhc3RlKExhdF9NZWQsIExuZ19NZWQsIHNlcCA9ICItLSIpCiAgICAgICAgICAgICAgICAgICAgICAgKQpWaWV3KGhlYWQoTExfU3RhdHNfVGVzdCkpCgpaaXBzMl9UZXN0IDwtIG11dGF0ZShaaXBzMiwKICAgICAgICAgICAgICAgICAgICAgVW5pcXVlTGF0TG5nID0gcGFzdGUobGF0LCBsbmcsIHNlcCA9ICItLSIpCiAgICAgICAgICAgICAgICAgICAgKQpzdHIoWmlwczJfVGVzdCkKVmlldyhoZWFkKFppcHMyX1Rlc3QpKQoKQ29tYmluZWRfVGVzdCA8LSBsZWZ0X2pvaW4oTExfU3RhdHNfVGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgWmlwczJfVGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCJVbmlxdWVMYXRMbmciID0gIlVuaXF1ZUxhdExuZyIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKVmlldyhDb21iaW5lZF9UZXN0KQpWaWV3KGZpbHRlcihDb21iaW5lZF9UZXN0LAogICAgICAgICAgICBiZXR3ZWVuKFJvd051bSwgMTk0OSwgMjA1MSkgJgogICAgICAgICAgICAgIGlzLm5hKGFkbWluQ29kZTIpCiAgICAgICAgICAgKQogICAgKQoKcGFnZXMyW1syXV0KYGBgCgoKRmVhdHVyZSBlbmdpbmVlcmluZy4KCkluc3BlY3RpbmcgaW5jaWRlbmNlcyBvZiBjb25zZWN1dGl2ZSBTdG9wX0lEcy4gVGhpcyBpcyBkb25lIGJlY2F1c2UgaW52ZXN0aWdhdGlvbiBzaG93ZWQgdGhhdCBtYW55IGNvbnNldXRpdmUgZXZlbnRzIG9jY3VyciBhdCB0aGUgc2FtZSBTdG9wX0lELCBidXQgd2l0aCB2YXJpb3VzIER3ZWxsX1RpbWVzLCBPZG9tZXRlcl9EaXN0YW5jZXMsIGV0Yy4gIEFsbCBvZiB3aGljaCBhZmZlY3QgY2FsY3VsYXRpb25zIGFuZCBhbmFseXNlcy4KCkNyZWF0ZSBkYXRhIG9uIHRoZSBydW5zIChjb25zZWN1dGl2ZSBTdG9wX0lEcykuCmBgYHtyfQoKU3RvcElEX1J1bnMgPC0gcmxlKEFsbERheXNfU3RvcElETmV3JFN0b3BJRF9DbGVhbikKClN0b3BJRF9SdW5zJGVuZHMgPC0gY3Vtc3VtKFN0b3BJRF9SdW5zJGxlbmd0aHMpCgpTdG9wSURfUnVucyRzdGFydHMgPC0gaWZlbHNlKGlzLm5hKGxhZyhTdG9wSURfUnVucyRlbmRzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhZyhTdG9wSURfUnVucyRlbmRzKSArIDEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCnN0cihTdG9wSURfUnVucykKIyBjbGFzcyhTdG9wSURfUnVucykKIyAKIyBTdG9wSURfUnVuc19kZiA8LSBkYXRhLmZyYW1lKHVuY2xhc3MoU3RvcElEX1J1bnMpKQojIHN0cihTdG9wSURfUnVuc19kZikKIyBjbGFzcyhTdG9wSURfUnVuc19kZikKIyBybShTdG9wSURfUnVuc19kZikKCmBgYAoKClRyeWluZyB0byBsaW5rIGRhdGEgb24gUnVuc0dyb3VwcyB3aXRoIHRoZSBvcmlnaW5hbCBkYXRhIChBbGxEYXlzX1NvcnRlZCkuIFRoZSBnb2FsIGlzIHRvIHNlbGVjdCBvbmx5IG9uZSByZWNvcmQgcGVyIFJ1bnNHcm91cCAtIHRoYXQgYmVpbmcgdGhlIHJlY29yZCB3aXRoIHRoZSBsb25nZXN0IER3ZWxsX1RpbWUuCgpJIGF0dGVtcHRlZCB0aGlzIGNvbXB1dGF0aW9uIHVzaW5nIGJvdGggZGF0YS5mcmFtZXMgKGRwbHlyKSBhbmQgZGF0YS50YWJsZXMgKGRhdGEudGFibGUpLiBIb3dldmVyLCB3aXRoIDIsODA5LDA2MiByb3dzIGluIG9uZSBkYXRhc2V0IGFuZCAzLDExOSw0NDMgcm93cyBpbiB0aGUgb3RoZXIgZGF0YXNldCwgdGhlIGN1cnJlbnQgY29tcHV0YXRpb24gdGltZSBpcyBvdmVyIDUgZGF5cy4uLnNvIEknbSB0cnlpbmcgYSBkaWZmZXJlbnQgc3RyYXRlZ3kgdG8gb25seSBzZWxlY3QgdGhlIGZpcnN0IHJlY29yZCBpbiBhIHJ1bi4KYGBge3J9CgojIENyZWF0ZSBhIFJ1bnNHcm91cCB2YXJpYWJsZSBmb3IgZWFjaCBydW4KIyBTdG9wSURfUnVuc19kZiRSdW5zR3JvdXAgPC0gcGFzdGUwKCJnIiwgc2VxKDE6bnJvdyhTdG9wSURfUnVuc19kZikKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgCiMgc3RyKFN0b3BJRF9SdW5zX2RmKQojIGhlYWQoU3RvcElEX1J1bnNfZGYsIDI1KQojIHRhaWwoU3RvcElEX1J1bnNfZGYsIDI1KQojIAojIFN0b3BJRF9SdW5zX2RmIDwtIFN0b3BJRF9SdW5zX2RmICU+JSAKIyAgIG11dGF0ZShSb3dOdW0gPSByb3dfbnVtYmVyKCkKIyAgICAgICAgICkKIyAKIyBzdHIoU3RvcElEX1J1bnNfZGYpCiMgaGVhZChTdG9wSURfUnVuc19kZiwgMjUpCiMgdGFpbChTdG9wSURfUnVuc19kZiwgMjUpCiMgCiMgCiMgIyBDb252ZXJ0aW5nIHRvIGRhdGEudGFibGVzIGZvciwgaG9wZWZ1bGx5LCBpbXByb3ZlZCBwZXJmb3JtYW5jZSAoc3BlZWQpIGluIGNvbXB1dGF0aW9uCiMgU3RvcElEX1J1bnNfZHQgPC0gZGF0YS50YWJsZShTdG9wSURfUnVuc19kZikKIyBzZXRrZXkoU3RvcElEX1J1bnNfZHQsIFJvd051bSkKIyBzdHIoU3RvcElEX1J1bnNfZHQpCiMgCiMgQWxsRGF5c19Tb3J0ZWRfZHQgPC0gZGF0YS50YWJsZShBbGxEYXlzX1NvcnRlZCkKIyBzZXRrZXkoQWxsRGF5c19Tb3J0ZWRfZHQsIFJvd051bV9PRykKIyBzdHIoQWxsRGF5c19Tb3J0ZWRfZHQpCiMgIyBybShBbGxEYXlzX1NvcnRlZF9kdCkKIyAKIyAKIyAjIEFjdHVhbCBsb29wIHRvIHBlcmZvcm0gdGhlIGNvbXB1dGF0aW9ucyBhbmQgbGluayB0byBvcmlnaW5hbCBkYXRhIChBbGxEYXlzX1NvcnRlZF9kdCkKIyBHcm91cERhdGEgPC0gbGlzdCgpCiMgZm9yKGkgaW4gMTpucm93KFN0b3BJRF9SdW5zX2R0KQojICAgICkgewojICAgYXNzaWduKHBhc3RlMCgiZ3JvdXBfIiwgaSksCiMgICAgICAgICAgICBTdG9wSURfUnVuc19kdFtSb3dOdW0gPT0gaSwgUnVuc0dyb3VwXQojICAgICAgICAgICApCiMgCiMgICAgICMjIyMjICBUaGUgY29kZSBiZWxvdyBpcyB0aGUgc2FtZSBjb2RlIGFzIGFib3ZlLCBidXQgZG9uZSB3aXRoIGRwbHlyICAjIyMjIwojIAojICAgICAjIGFzc2lnbihwYXN0ZTAoImdyb3VwXyIsIGkpLAojICAgIyAgICAgICAgZmlsdGVyKFN0b3BJRF9SdW5zX2RmLAojICAgIyAgICAgICAgICAgICAgIFJvd051bSA9PSBpCiMgICAjICAgICAgICAgICAgICApICU+JSAKIyAgICMgICAgICAgICAgc2VsZWN0KFJ1bnNHcm91cCkKIyAgICMgICAgICAgKQojIAojICAgYXNzaWduKHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9zdGFydCIpLAojICAgICAgICAgIFN0b3BJRF9SdW5zX2R0W1Jvd051bSA9PSBpLCBzdGFydHNdCiMgICAgICAgICApCiMgCiMgICBhc3NpZ24ocGFzdGUwKCJncm91cF8iLCBpLCAiX2VuZCIpLAojICAgICAgICAgIFN0b3BJRF9SdW5zX2R0W1Jvd051bSA9PSBpLCBlbmRzXQojICAgICAgICAgKQojIAojICAgYXNzaWduKHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9yb3dzIiksCiMgICAgICAgICAgQWxsRGF5c19Tb3J0ZWRfZHRbUm93TnVtX09HID49IGFzLm51bWVyaWMoZ2V0KHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9zdGFydCIpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgUm93TnVtX09HIDw9IGFzLm51bWVyaWMoZ2V0KHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9lbmQiKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgUnVuc0dyb3VwIDo9IGFzLmNoYXJhY3RlcihnZXQocGFzdGUwKCJncm91cF8iLCBpKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgICAgICAgICAgICAgICAgICBdCiMgCiMgICAgICMjIyMjICBUaGUgY29kZSBiZWxvdyBpcyB0aGUgc2FtZSBhcyB0aGUgY29kZSBhYm92ZSwgYnV0IGRvbmUgd2l0aCBkcGx5ciAgIyMjIyMKIyAKIyAgICAgICAgICAjIGZpbHRlcihBbGxEYXlzX1NvcnRlZCwKIyAgICAgICAgICAjICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywKIyAgICAgICAgICAjICAgICAgICAgICAgICAgIGFzLm51bWVyaWMoZ2V0KHBhc3RlMCgiZ3JvdXBfIiwgaSwgIl9zdGFydCIpCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICApLAojICAgICAgICAgICMgICAgICAgICAgICAgICAgYXMubnVtZXJpYyhnZXQocGFzdGUwKCJncm91cF8iLCBpLCAiX2VuZCIpCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICkgJT4lIAojICAgICAgICAgICMgICBtdXRhdGUoUnVuc0dyb3VwID0gYXMuY2hhcmFjdGVyKGdldChwYXN0ZTAoImdyb3VwXyIsIGkpCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICAjICAgICAgICApCiMgICAgICAgICApCiMgCiMgICBHcm91cERhdGFbW2ldXSA8LSBnZXQocGFzdGUwKCJncm91cF8iLCBpLCAiX3Jvd3MiKSkKIyAKIyAgIG1lc3NhZ2UoIlByb2Nlc3NpbmcgR3JvdXAgIiwgaSwgIiBvZiAyLDgwOSwwNjIiKQojIH0KIyAKIyAKIyBHcm91cERhdGFfZGYgPC0gcmJpbmQuZmlsbChHcm91cERhdGEpCiMgc3RyKEdyb3VwRGF0YV9kZikKIyBoZWFkKEdyb3VwRGF0YV9kZikKIyB0YWlsKEdyb3VwRGF0YV9kZikKIyAjIHJtKEdyb3VwRGF0YV9kZikKIyAKIyAKIyBncm91cF8xCiMgZ3JvdXBfMV9zdGFydAojIGdyb3VwXzFfZW5kCiMgZ3JvdXBfMV9yb3dzCiMgZ3JvdXBfMl9yb3dzCiMgZ3JvdXBfM19yb3dzCiMgZ3JvdXBfNTBfcm93cwojIHN0cihncm91cF81MF9yb3dzKQojIGdyb3VwXzI4MDkwNjJfcm93cwojIEdyb3VwRGF0YVtbMV1dCiMgR3JvdXBEYXRhW1s1MF1dCiMgCiMgCiMgIyMjIyMgIFRlc3RpbmcgQXJlYSAoQmVsb3cpICAjIyMjIwojICMjIyMjICBUZXN0aW5nIEFyZWEgKEJlbG93KSAgIyMjIyMKIyAjIyMjIyAgVGVzdGluZyBBcmVhIChCZWxvdykgICMjIyMjCiMgCiMgIyBoZWFkKFN0b3BJRF9SdW5zJHN0YXJ0cywgMjApCiMgIyBoZWFkKEFsbERheXNfTmV3T3JkZXIkU3RvcF9JRCwgMjApCiMgIyAKIyAjIAojICMgZGF0IDwtIGFzLmRhdGEuZnJhbWUoYygxLDEsNyw3LDcsOSw2LDgsMiwyLDIsMSwxLDEsMSwxKSkKIyAjIGNvbG5hbWVzKGRhdClbMV0gPC0gImRhdCIKIyAjIHIgPC0gcmxlKGRhdCRkYXQpCiMgIyBkYXQkcnVuIDwtIHJlcChyJGxlbmd0aHMsIHIkbGVuZ3RocykKIyAjIGRhdCRydW5MYWcgPC0gbGFnKGRhdCRydW4pCiMgIyBkYXQkY29uZCA8LSByZXAociR2YWx1ZXMsIHIkbGVuZ3RocykKIyAjIGRhdAojICMgVmlldyhkYXQpCgpgYGAKCgpXaGVuIGNvbnNlY3V0aXZlIFN0b3BfSUQgb2NjdXJycywgb25seSB0YWtlIHRoZSBmaXJzdCBvY2N1cnJlbmNlLiBUaGlzIGlzIGRvbmUgYmVjYXVzZSB0aGUgY29tcHV0YXRpb24gdGltZSB0byBzZWxlY3Qgb25seSB0aGUgcmVjb3JkIHdpdGggdGhlIGxvbmdlc3QgRHdlbGxfVGltZSBmb3IgZWFjaCBydW4gd2FzIHRvbyBsb25nIChvdmVyIDUgZGF5cykuCgpUaGlzIGlzIHByb2JhYmx5IGxlc3MgdGhhbiBpZGVhbCB3aXRoIHJlZ2FyZHMgdG8gRHdlbGxfVGltZSwgYnV0IHNob3VsZCBub3QgbWFrZSBtdWNoIGRpZmZlcmVuY2UgZm9yIGNhbGN1bGF0aW9ucyBvZiB0cmF2ZWwgdGltZSwgc3BlZWQsIGV0Yy4KYGBge3J9CgpBbGxEYXlzX0ZpcnN0U3RvcElEIDwtIEFsbERheXNfU3RvcElETmV3W1N0b3BJRF9SdW5zJHN0YXJ0cywgXQoKZGltKEFsbERheXNfU3RvcElETmV3KQpkaW0oQWxsRGF5c19GaXJzdFN0b3BJRCkKCm5yb3coQWxsRGF5c19TdG9wSUROZXcpIC0gbnJvdyhBbGxEYXlzX0ZpcnN0U3RvcElEKQoKcm0oQWxsRGF5c19TdG9wSUROZXcpCnJtKFN0b3BJRF9SdW5zKQpzdHIoQWxsRGF5c19GaXJzdFN0b3BJRCkKCmBgYAoKCkZlYXR1cmUgZW5naW5lZXJpbmcuCgpDcmVhdGluZyBuZXcgdmFyaWFibGVzLgpgYGB7cn0KCkFsbERheXNfQWRkVmFycyA8LSBtdXRhdGUoQWxsRGF5c19GaXJzdFN0b3BJRCwKICAgICAgICAgICAgICAgICAgICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZV9NaSA9IE9kb21ldGVyX0Rpc3RhbmNlIC8gNTI4MCwgIzUsMjgwIGZlZXQgaW4gMSBtaWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgRHdlbGxfVGltZTIgPSBhcy5udW1lcmljKERlcGFydHVyZV9UaW1lIC0gRXZlbnRfVGltZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9ZciA9IGFzLmludGVnZXIoeWVhcihFdmVudF9UaW1lKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9NdGggPSBhcy5pbnRlZ2VyKG1vbnRoKEV2ZW50X1RpbWUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0RhdGUgPSBkYXkoRXZlbnRfVGltZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXkgPSB3ZGF5KEV2ZW50X1RpbWUsIGxhYmVsID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9IciA9IGhvdXIoRXZlbnRfVGltZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9NaW4gPSBtaW51dGUoRXZlbnRfVGltZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwID0gZmFjdG9yKGlmZWxzZShFdmVudF9UaW1lX0hyIDwgMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDBfMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFdmVudF9UaW1lX0hyIDwgNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDNfNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFdmVudF9UaW1lX0hyIDwgOSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDZfOCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShFdmVudF9UaW1lX0hyIDwgMTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXA5XzExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCAxNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDEyXzE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCAxOCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDE1XzE3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCAyMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDE4XzIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKEV2ZW50X1RpbWVfSHIgPCAyNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDIxXzIzIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkpKSkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiR3JvdXAwXzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDNfNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwNl84IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXA5XzExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAxMl8xNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyb3VwMTVfMTciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcm91cDE4XzIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3JvdXAyMV8yMyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgKQoKcm0oQWxsRGF5c19GaXJzdFN0b3BJRCkKc3RyKEFsbERheXNfQWRkVmFycykKCgojIGdyb3VwX2J5KEFsbERheXNfQWRkVmFycywKIyAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAKIyAgICAgICAgICkgJT4lIAojICAgc3VtbWFyaXNlKENudHMgPSBuKCkKIyAgICAgICAgICAgICkKCgojIFZpZXcoaGVhZChmaWx0ZXIoQWxsRGF5c19BZGRWYXJzLAojICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9IciA9PSAwCiMgICAgICAgICAgICAgICAgICksCiMgICAgICAgICAgIDUwCiMgICAgICAgICAgKQojICAgICApCgojIFZpZXcoaGVhZChBbGxEYXlzX0FkZFZhcnMsIDUwKSkKCmBgYAoKCjwhLS0gRnVuY3Rpb24gZm9yIGNhbGN1bGF0aW5nIHRoZSBkaXN0YW5jZSB0cmF2ZWxlZCBiYXNlZCBvbiB0aGUgSGF2ZXJzaW5lIGZvcm11bGEuICBPcmlnaW5hbCBjb2RlIGZyb206IGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL2dyZWF0LWNpcmNsZS1kaXN0YW5jZS1jYWxjdWxhdGlvbnMtaW4tci8gLS0+CjwhLS0gYGBge3J9IC0tPgoKPCEtLSBnY2QuaGYgPC0gZnVuY3Rpb24obG9uZzEsIGxhdDEsIGxvbmcyLCBsYXQyKSB7IC0tPgo8IS0tICAgUiA8LSA2MzcxICMgRWFydGggbWVhbiByYWRpdXMgW2ttXSAtLT4KPCEtLSAgIGRlbHRhLmxvbmcgPC0gKGxvbmcyIC0gbG9uZzEpIC0tPgo8IS0tICAgZGVsdGEubGF0IDwtIChsYXQyIC0gbGF0MSkgLS0+CjwhLS0gICBhIDwtIHNpbihkZWx0YS5sYXQvMileMiArIGNvcyhsYXQxKSAqIGNvcyhsYXQyKSAqIHNpbihkZWx0YS5sb25nLzIpXjIgLS0+CjwhLS0gICBjIDwtIDIgKiBhc2luKG1pbigxLHNxcnQoYSkpKSAtLT4KPCEtLSAgIGQgPSBSICogYyAqIDAuNjIxMzcxICMgMSBrbSA9IDAuNjIxMzcxIG1pbGVzIC0tPgo8IS0tICAgcmV0dXJuKGQpICMgRGlzdGFuY2UgaW4gbWlsZXMgLS0+CjwhLS0gfSAtLT4KCjwhLS0gYGBgIC0tPgoKCkZlYXR1cmUgZW5naW5lZXJpbmcuCgpDcmVhdGluZyBtb3JlIHZhcmlhYmxlcy4gQ3JlYXRpbmcgYSBCdXNFdmVudCByb3cgbnVtYmVyIGZvciBmdXR1cmUgaWRlbnRpZmljYXRpb24gcHVycG9zZXMuIFRoZW4sIGNyZWF0aW5nIHZhcmlvdXMgdmFyaWFibGVzIHRvIGFuYWx5emUgZGlzdGFuY2UgdHJhdmVsZWQgYW5kIHNwZWVkLgpgYGB7cn0KCkFsbERheXNfQnVzRGF5IDwtIGdyb3VwX2J5KEFsbERheXNfQWRkVmFycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgQnVzX0lELAogICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0RhdGUKICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoQnVzRGF5X0V2ZW50TnVtID0gcm93X251bWJlcigpLCAgIyB1c2VkIHRvIGlkZW50aWZ5IEJ1cyBtb3ZlbWVudHMgb24gYSBwYXJ0aWN1bGFyIGRhdGUKICAgICAgICAgCiAgICAgICAgIFJvdXRlX0xhZzEgPSBsYWcoUm91dGUpLCAgIyB1c2VkIGluIGZ1dHVyZSBhbmFseXNlcyB0byBpZGVudGlmeSBSb3V0ZSBjaGFuZ2VzCiAgICAgICAgIFJvdXRlQWx0X0xhZzEgPSBsYWcoUm91dGVBbHQpLCAgIyB1c2VkIGluIGZ1dHVyZSBhbmFseXNlcyB0byBpZGVudGlmeSBSb3V0ZUFsdCAoZGlyZWN0aW9uKSBjaGFuZ2VzCiAgICAgICAgIAogICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxID0gbGFnKE9kb21ldGVyX0Rpc3RhbmNlKSwKICAgICAgICAgCiAgICAgICAgIExhdGl0dWRlX0wxID0gbGFnKExhdGl0dWRlKSwKICAgICAgICAgTG9uZ2l0dWRlX0wxID0gbGFnKExvbmdpdHVkZSksCiAgICAgICAgICMgTGF0X1JhZGlhbiA9IExhdGl0dWRlKnBpLzE4MCwKICAgICAgICAgIyBMb25nX1JhZGlhbiA9IExvbmdpdHVkZSpwaS8xODAsCiAgICAgICAgICMgTGF0X1JhZGlhbl9MMSA9IGxhZyhMYXRfUmFkaWFuKSwKICAgICAgICAgIyBMb25nX1JhZGlhbl9MMSA9IGxhZyhMb25nX1JhZGlhbiksCiAgICAgICAgIAogICAgICAgICAjIGFjY291bnRpbmcgZm9yIHBvdGVudGlhbCBuZWdhdGl2ZSBkaXN0YW5jZXMKICAgICAgICAgVHJhdmVsRGlzdGFuY2VfRnQgPSBpZmVsc2UoT2RvbWV0ZXJfRGlzdGFuY2UgPiBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZSAtIE9kb21ldGVyX0Rpc3RhbmNlX0xhZzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPSBUcmF2ZWxEaXN0YW5jZV9GdCAvIDUyODAsICM1LDI4MCBmZWV0IGluIDEgbWlsZQogICAgICAgICAKICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9NaTIgPSBnY2QuaGYobG9uZzEgPSBMb25nX1JhZGlhbl9MMSwKICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0MSA9IExhdF9SYWRpYW5fTDEsCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvbmcyID0gTG9uZ19SYWRpYW4sCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdDIgPSBMYXRfUmFkaWFuCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgPSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpZmVsc2UoKGlzLm5hKExvbmdpdHVkZV9MMSkgfCBpcy5uYShMYXRpdHVkZV9MMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3RIYXZlcnNpbmUoY2JpbmQoTG9uZ2l0dWRlX0wxLCBMYXRpdHVkZV9MMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2JpbmQoTG9uZ2l0dWRlLCBMYXRpdHVkZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKiAwLjAwMDYyMTM3MSwgIyAwLjAwMDYyMTM3MSBtaWxlcyA9IDEgbWV0ZXIKICAgICAgICAgCiAgICAgICAgICMgYWNjb3VudGluZyBmb3IgcG90ZW50aWFsIG5lZ2F0aXZlIHRpbWVzCiAgICAgICAgIFRyYXZlbFRpbWVfU2VjID0gYXMubnVtZXJpYyhpZmVsc2UoRXZlbnRfVGltZSA+IGxhZyhEZXBhcnR1cmVfVGltZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZSAtIGxhZyhEZXBhcnR1cmVfVGltZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVHJhdmVsVGltZV9IciA9IFRyYXZlbFRpbWVfU2VjIC8gMzYwMCwgIyAzLDYwMCBzZWNvbmRzIGluIDEgaG91cgogICAgICAgICAKICAgICAgICAgIyBhY2NvdW50aW5nIGZvciBwb3RlbnRpYWwgbmVnYXRpdmUgb3IgemVybyB0cmF2ZWwgdGltZXMKICAgICAgICAgU3BlZWRBdmdfTXBoID0gaWZlbHNlKFRyYXZlbFRpbWVfSHIgPiAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgLyBUcmF2ZWxUaW1lX0hyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgCiAgICAgICAgIFN0YXJ0X0lEID0gbGFnKFN0b3BJRF9DbGVhbiksCiAgICAgICAgIFN0YXJ0X0Rlc2MgPSBsYWcoU3RvcF9EZXNjKSwKICAgICAgICAgU3RhcnRTdG9wX0lEID0gaWZlbHNlKGlzLm5hKFN0YXJ0X0lEKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCJOVUxMIiwgU3RvcElEX0NsZWFuLCBzZXAgPSAiLS0iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhc3RlKFN0YXJ0X0lELCBTdG9wSURfQ2xlYW4sIHNlcCA9ICItLSIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICApICU+JSAKICBhcy5kYXRhLmZyYW1lKCkKCgpybShBbGxEYXlzX0FkZFZhcnMpCnN0cihBbGxEYXlzX0J1c0RheSkKCiMgc3VtbWFyeShBbGxEYXlzX0J1c0RheSkKCiMgVmlldyh0YWlsKEFsbERheXNfQnVzRGF5LCA1MCkpCgpgYGAKCgpJbnNwZWN0aW5nIGZvciBpc3N1ZXMgd2l0aCBTdGFydFN0b3BfSUQgKHdoZXJlIHRoZSB2YWx1ZSBpcyBlaXRoZXIgTkEgb3IgY29udGFpbnMgTlVMTCkuIFRoZXkgT05MWSBleGlzdCB3aGVuIEJ1c0RheV9FdmVudE51bSA9IDEgKHdoaWNoIGlzIGJ5IGRlc2lnbikuIFNvIGV2ZXJ5dGhpbmcgbG9va3MgT0suCmBgYHtyfQoKVmlldyhncm91cF9ieShBbGxEYXlzX0J1c0RheSwKICAgICAgICAgICAgICBTdGFydFN0b3BfSUQKICAgICAgICAgICAgICkgJT4lIAogICAgICAgc3VtbWFyaXNlKAogICAgICAgICBDbnQgPSBuKCkKICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShkZXNjKENudCkKICAgICAgICAgICAgICApCiAgICApCgpWaWV3KGZpbHRlcihBbGxEYXlzX0J1c0RheSwKICAgICAgICAgICAgKGlzLm5hKFN0YXJ0U3RvcF9JRCkgfAogICAgICAgICAgICAgIHN0cl9kZXRlY3QoU3RhcnRTdG9wX0lELCAiTlVMTCIpCiAgICAgICAgICAgICkgJgogICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxCiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKU3RhdHMgKHF1YW50aWxlcykgb3ZlcmFsbCBmb3IgVHJhdmVsRGlzdGFuY2VfTWkuCmBgYHtyfQoKUXVhbnRpbGVzX2R0IDwtIEFsbERheXNfQnVzRGF5ICU+JSAKICBtdXRhdGUoVERfTWlfcTIgPSBxdWFudGlsZSh4ID0gVHJhdmVsRGlzdGFuY2VfTWksIHByb2JzID0gMC4wMiwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfcTk4ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuOTgsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19xMiA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjAyLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfcTk4ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfU2VjLCBwcm9icyA9IDAuOTgsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX3EyID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfSHIsIHByb2JzID0gMC4wMiwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfSHJfcTk4ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfSHIsIHByb2JzID0gMC45OCwgbmEucm0gPSBUUlVFKQogICAgICAgICkgJT4lIAogIGRhdGEudGFibGUoKQoKClN0YXRzIDwtIFF1YW50aWxlc19kdCAlPiUgCiAgbXV0YXRlKFREX01pX01lYW4gPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBURF9NaV9NZWFuX0YgPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX3EyIDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFREX01pX01lZCA9IG1lZGlhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfTWVkX0YgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWlbVERfTWlfcTIgPD0gVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaSA8PSBURF9NaV9xOThdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlbVERfTWlfcTIgPD0gVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaSA8PSBURF9NaV9xOThdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAKICAgICAgICAgVFRfU2VjX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfU2VjLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfTWVhbl9GID0gbWVhbihUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfcTIgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfU2VjX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX01lZF9GID0gbWVkaWFuKFRyYXZlbFRpbWVfU2VjW1RUX1NlY19xMiA8PSBUcmF2ZWxUaW1lX1NlYyAmIFRyYXZlbFRpbWVfU2VjIDw9IFRUX1NlY19xOThdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfU2VjKQogICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfU2VjX0NudF9GID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfcTIgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfcTk4XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKCiAgICAgICAgIFRUX0hyX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX01lYW5fRiA9IG1lYW4oVHJhdmVsVGltZV9IcltUVF9Icl9xMiA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9xOThdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfTWVkID0gbWVkaWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX01lZF9GID0gbWVkaWFuKFRyYXZlbFRpbWVfSHJbVFRfSHJfcTIgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfcTk4XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX0hyKQogICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUVF9Icl9DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcltUVF9Icl9xMiA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9xOThdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKSAlPiUgCiAgZGF0YS5mcmFtZSgpCgpybShBbGxEYXlzX0J1c0RheSkKcm0oUXVhbnRpbGVzX2R0KQpzdHIoU3RhdHMpCiMgVmlldyhoZWFkKFN0YXRzLCA1MCkpCgpgYGAKCgpTdGF0cyBmb3IgU3RhcnRTdG9wX0lELgpgYGB7cn0KClF1YW50aWxlc19TU19kdCA8LSBncm91cF9ieShTdGF0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRAogICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoVERfTWlfU1NfcTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsRGlzdGFuY2VfTWksIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NfcTk1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbERpc3RhbmNlX01pLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU19xNSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX1NlYywgcHJvYnMgPSAwLjA1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfU1NfcTk1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfU2VjLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTX3E1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfSHIsIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfSHJfU1NfcTk1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfSHIsIHByb2JzID0gMC45NSwgbmEucm0gPSBUUlVFKQogICAgICAgICkgJT4lIAogIGRhdGEudGFibGUoKQoKClN0YXRzX1N0U3QgPC0gZ3JvdXBfYnkoUXVhbnRpbGVzX1NTX2R0LAogICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRAogICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFREX01pX1NTX01lYW4gPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBURF9NaV9TU19NZWFuX0YgPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFREX01pX1NTX01lZCA9IG1lZGlhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NfTWVkX0YgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWlbVERfTWlfU1NfcTUgPD0gVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaSA8PSBURF9NaV9TU19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9TU19DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9TU19DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlbVERfTWlfU1NfcTUgPD0gVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaSA8PSBURF9NaV9TU19xOTVdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAKICAgICAgICAgVFRfU2VjX1NTX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfU2VjLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfU1NfTWVhbl9GID0gbWVhbihUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfU1NfcTUgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfU2VjX1NTX01lZCA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlYywgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTX01lZF9GID0gbWVkaWFuKFRyYXZlbFRpbWVfU2VjW1RUX1NlY19TU19xNSA8PSBUcmF2ZWxUaW1lX1NlYyAmIFRyYXZlbFRpbWVfU2VjIDw9IFRUX1NlY19TU19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19TU19DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSksCiAgICAgICAgIFRUX1NlY19TU19DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9TZWNbVFRfU2VjX1NTX3E1IDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX1NTX3E5NV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKCiAgICAgICAgIFRUX0hyX1NTX01lYW4gPSBtZWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTX01lYW5fRiA9IG1lYW4oVHJhdmVsVGltZV9IcltUVF9Icl9TU19xNSA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9TU19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfU1NfTWVkID0gbWVkaWFuKFRyYXZlbFRpbWVfSHIsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTX01lZF9GID0gbWVkaWFuKFRyYXZlbFRpbWVfSHJbVFRfSHJfU1NfcTUgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfU1NfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfU1NfQ250ID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX0hyKSksCiAgICAgICAgIFRUX0hyX1NTX0NudF9GID0gc3VtKCFpcy5uYShUcmF2ZWxUaW1lX0hyW1RUX0hyX1NTX3E1IDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX1NTX3E5NV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICApICU+JSAKICBkYXRhLmZyYW1lKCkKCnJtKFN0YXRzKQpybShRdWFudGlsZXNfU1NfZHQpCnN0cihTdGF0c19TdFN0KQojIFZpZXcoaGVhZChTdGF0c19TdFN0LCA1MCkpCgpgYGAKCgpTdGF0cyBmb3IgU3RhcnRTdG9wX0lEIHdpdGggRXZlbnRfVGltZV9Ickdyb3VwLgpgYGB7cn0KClF1YW50aWxlc19TU0hHX2R0IDwtIGdyb3VwX2J5KFN0YXRzX1N0U3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFREX01pX1NTSEdfcTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsRGlzdGFuY2VfTWksIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NIR19xOTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsRGlzdGFuY2VfTWksIHByb2JzID0gMC45NSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTSEdfcTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9TZWMsIHByb2JzID0gMC4wNSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfU2VjX1NTSEdfcTk1ID0gcXVhbnRpbGUoeCA9IFRyYXZlbFRpbWVfU2VjLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX0hyX1NTSEdfcTUgPSBxdWFudGlsZSh4ID0gVHJhdmVsVGltZV9IciwgcHJvYnMgPSAwLjA1LCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9Icl9TU0hHX3E5NSA9IHF1YW50aWxlKHggPSBUcmF2ZWxUaW1lX0hyLCBwcm9icyA9IDAuOTUsIG5hLnJtID0gVFJVRSkKICAgICAgICApICU+JSAKICBkYXRhLnRhYmxlKCkKCgpTdGF0c19TdFN0X0hyR3JwIDwtIGdyb3VwX2J5KFF1YW50aWxlc19TU0hHX2R0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShURF9NaV9TU0hHX01lYW4gPSBtZWFuKFRyYXZlbERpc3RhbmNlX01pLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBURF9NaV9TU0hHX01lYW5fRiA9IG1lYW4oVHJhdmVsRGlzdGFuY2VfTWlbVERfTWlfU1NIR19xNSA8PSBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pIDw9IFREX01pX1NTSEdfcTk1XSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBURF9NaV9TU0hHX01lZCA9IG1lZGlhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVERfTWlfU1NIR19NZWRfRiA9IG1lZGlhbihUcmF2ZWxEaXN0YW5jZV9NaVtURF9NaV9TU0hHX3E1IDw9IFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWkgPD0gVERfTWlfU1NIR19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVERfTWlfU1NIR19DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFREX01pX1NTSEdfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pW1REX01pX1NTSEdfcTUgPD0gVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaSA8PSBURF9NaV9TU0hHX3E5NV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAKICAgICAgICAgVFRfU2VjX1NTSEdfTWVhbiA9IG1lYW4oVHJhdmVsVGltZV9TZWMsIG5hLnJtID0gVFJVRSksCiAgICAgICAgIFRUX1NlY19TU0hHX01lYW5fRiA9IG1lYW4oVHJhdmVsVGltZV9TZWNbVFRfU2VjX1NTSEdfcTUgPD0gVHJhdmVsVGltZV9TZWMgJiBUcmF2ZWxUaW1lX1NlYyA8PSBUVF9TZWNfU1NIR19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfU2VjX1NTSEdfTWVkID0gbWVkaWFuKFRyYXZlbFRpbWVfU2VjLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICBUVF9TZWNfU1NIR19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX1NlY1tUVF9TZWNfU1NIR19xNSA8PSBUcmF2ZWxUaW1lX1NlYyAmIFRyYXZlbFRpbWVfU2VjIDw9IFRUX1NlY19TU0hHX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRUX1NlY19TU0hHX0NudCA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9TZWMpKSwKICAgICAgICAgVFRfU2VjX1NTSEdfQ250X0YgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfU2VjW1RUX1NlY19TU0hHX3E1IDw9IFRyYXZlbFRpbWVfU2VjICYgVHJhdmVsVGltZV9TZWMgPD0gVFRfU2VjX1NTSEdfcTk1XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKCiAgICAgICAgIFRUX0hyX1NTSEdfTWVhbiA9IG1lYW4oVHJhdmVsVGltZV9IciwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfSHJfU1NIR19NZWFuX0YgPSBtZWFuKFRyYXZlbFRpbWVfSHJbVFRfSHJfU1NIR19xNSA8PSBUcmF2ZWxUaW1lX0hyICYgVHJhdmVsVGltZV9IciA8PSBUVF9Icl9TU0hHX3E5NV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfU1NIR19NZWQgPSBtZWRpYW4oVHJhdmVsVGltZV9IciwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgVFRfSHJfU1NIR19NZWRfRiA9IG1lZGlhbihUcmF2ZWxUaW1lX0hyW1RUX0hyX1NTSEdfcTUgPD0gVHJhdmVsVGltZV9IciAmIFRyYXZlbFRpbWVfSHIgPD0gVFRfSHJfU1NIR19xOTVdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgVFRfSHJfU1NIR19DbnQgPSBzdW0oIWlzLm5hKFRyYXZlbFRpbWVfSHIpKSwKICAgICAgICAgVFRfSHJfU1NIR19DbnRfRiA9IHN1bSghaXMubmEoVHJhdmVsVGltZV9IcltUVF9Icl9TU0hHX3E1IDw9IFRyYXZlbFRpbWVfSHIgJiBUcmF2ZWxUaW1lX0hyIDw9IFRUX0hyX1NTSEdfcTk1XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICApICU+JSAKICBkYXRhLmZyYW1lKCkKCnJtKFN0YXRzX1N0U3QpCnJtKFF1YW50aWxlc19TU0hHX2R0KQpzdHIoU3RhdHNfU3RTdF9IckdycCkKIyBWaWV3KGhlYWQoU3RhdHNfU3RTdF9IckdycCwgNTApKQoKYGBgCgoKRmVhdHVyZSBlbmdpbmVlcmluZy4KCkNyZWF0aW5nIGEgQnVzRXZlbnRSb3V0ZSByb3cgbnVtYmVyLCBhbmQgYSBSb3V0ZUFsdF9MYWcxIGluZGljYXRvciBmb3IgZnV0dXJlIGlkZW50aWZpY2F0aW9uIHB1cnBvc2VzLiAKYGBge3J9CgojIHJtKFF1YW50aWxlc19kdCkKIyBybShRdWFudGlsZXNfU1NfZHQpCiMgcm0oQWxsRGF5c19CdXNEYXkpCiMgcm0oUXVhbnRpbGVzX1NTSEdfZHQpCiMgcm0oU3RhdHNfU3RTdCkKCiMgQWxsRGF5c19CdXNEYXlSb3V0ZSA8LSBncm91cF9ieShTdGF0c19TdFN0X0hyR3JwLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQnVzX0lELAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXRlLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUm91dGUKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiMgICBtdXRhdGUoUm91dGVBbHRfTGFnMiA9IGxhZyhSb3V0ZUFsdCkgICMgdXNlZCBpbiBmdXR1cmUgYW5hbHlzZXMgdG8gaWRlbnRpZnkgUm91dGVBbHQgKGRpcmVjdGlvbikgY2hhbmdlcwojICAgICAgICAgIAojICAgICAgICAgICMgT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSA9IGxhZyhPZG9tZXRlcl9EaXN0YW5jZSksCiMgICAgICAgICAgIyAKIyAgICAgICAgICAjICMgYWNjb3VudGluZyBmb3IgcG90ZW50aWFsIG5lZ2F0aXZlIGRpc3RhbmNlcwojICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfRnQgPSBpZmVsc2UoT2RvbWV0ZXJfRGlzdGFuY2UgPj0gT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSwKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9kb21ldGVyX0Rpc3RhbmNlIC0gT2RvbWV0ZXJfRGlzdGFuY2VfTGFnMSwKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiMgICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9NaSA9IFRyYXZlbERpc3RhbmNlX0Z0IC8gNTI4MCwgIzUsMjgwIGZlZXQgaW4gMSBtaWxlCiMgICAgICAgICAgIyAKIyAgICAgICAgICAjICMgYWNjb3VudGluZyBmb3IgcG90ZW50aWFsIG5lZ2F0aXZlIHRpbWVzCiMgICAgICAgICAgIyBUcmF2ZWxUaW1lX1NlYyA9IGFzLm51bWVyaWMoaWZlbHNlKEV2ZW50X1RpbWUgPj0gbGFnKERlcGFydHVyZV9UaW1lKSwKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZSAtIGxhZyhEZXBhcnR1cmVfVGltZSksCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQojICAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKIyAgICAgICAgICAjIFRyYXZlbFRpbWVfSHIgPSBUcmF2ZWxUaW1lX1NlYyAvIDM2MDAsICMgMyw2MDAgc2Vjb25kcyBpbiAxIGhvdXIKIyAgICAgICAgICAjIAojICAgICAgICAgICMgIyBhY2NvdW50aW5nIGZvciBwb3RlbnRpYWwgbmVnYXRpdmUgb3IgemVybyB0cmF2ZWwgdGltZXMKIyAgICAgICAgICAjIFNwZWVkQXZnX01waCA9IGlmZWxzZShUcmF2ZWxUaW1lX0hyID4gMCwKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSAvIFRyYXZlbFRpbWVfSHIsCiMgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgTkEKIyAgICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICkKIyAgICAgICAgICkgJT4lIAojICAgZGF0YS5mcmFtZSgpCiMgCiMgcm0oU3RhdHNfU3RTdF9IckdycCkKIyBzdHIoQWxsRGF5c19CdXNEYXlSb3V0ZSkKCmBgYAoKCkZlYXR1cmUgZW5naW5lZXJpbmcuCgpDYWxjdWxhdGluZyBhIHZhcmlhYmxlIHRvIGtub3cgaWYgdGhlIFJvdXRlQWx0IGNoYW5nZWQuIENvdWxkIGJlIHVzZWZ1bCBpbiBoZWxwaW5nIGlkZW50aWZ5aW5nIHdlaXJkbmVzcyBpbiBjYWxjdWxhdGVkIGRpc3RhbmNlcyBhbmQgc3BlZWRzLgpgYGB7cn0KCiMgcm0oU3RhdHNfU3RTdF9IckdycCkKCkFsbERheXNfRGlyQ2hhbmdlIDwtIFN0YXRzX1N0U3RfSHJHcnAgJT4lICAjIEFsbERheXNfQnVzRGF5Um91dGUgJT4lIAogIG11dGF0ZShSdGVDaGFuZ2UgPSBpZmVsc2UoUm91dGUgPT0gUm91dGVfTGFnMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGFuZ2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIFJ0ZUNoYW5nZTIgPSBmYWN0b3IoaWZlbHNlKGlzLm5hKFJ0ZUNoYW5nZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSdGVDaGFuZ2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBEaXJDaGFuZ2UgPSBpZmVsc2UoUm91dGVBbHQgPT0gUm91dGVBbHRfTGFnMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGFuZ2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIERpckNoYW5nZTIgPSBmYWN0b3IoaWZlbHNlKGlzLm5hKERpckNoYW5nZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaXJDaGFuZ2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKQoKIyBybShBbGxEYXlzX0J1c0RheVJvdXRlKQpybShTdGF0c19TdFN0X0hyR3JwKQpzdHIoQWxsRGF5c19EaXJDaGFuZ2UpCgpWaWV3KGZpbHRlcihBbGxEYXlzX0RpckNoYW5nZSwKICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDI1NzAwNjAsIDI1NzAwODApCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBzZWxlY3QoLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgICAgKQogICAgKQoKYGBgCgoKUmUtb3JkZXJpbmcgdGhlIHZhcmlhYmxlcyB0byBlYXNlIHdpdGggY29tcHJlaGVuc2lvbi4KYGBge3J9CgpBbGxEYXlzX05ld09yZGVyIDwtICBzZWxlY3QoQWxsRGF5c19EaXJDaGFuZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBSb3dOdW1fT0csCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c19JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJvdXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUnRlQ2hhbmdlMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJvdXRlQWx0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSb3V0ZUFsdF9MYWcxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJvdXRlX0RpcmVjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0b3BfU2VxdWVuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydF9JRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN0YXJ0X0Rlc2MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wSURfQ2xlYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdG9wSURfSW5kaWNhdG9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RvcF9EZXNjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X0Rlc2NyaXB0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9ZciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV2ZW50X1RpbWVfTXRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9EYXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9NaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVwYXJ0dXJlX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEd2VsbF9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRHdlbGxfVGltZTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgTGF0aXR1ZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb25naXR1ZGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBIZWFkaW5nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPZG9tZXRlcl9EaXN0YW5jZV9MYWcxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgT2RvbWV0ZXJfRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9GdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX3EyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfcTk4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19xOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX3E1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19xOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfTWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfTWVkX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX0NudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX0NudF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU0hHX0NudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19xMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19xOTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfcTk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19xOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfTWVkX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX0hyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfcTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9xOTgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19xNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX3E5NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTSEdfcTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX3E5NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19NZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9NZWRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX01lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19NZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU0hHX01lZF9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfQ250X0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19DbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9Icl9TU19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX0hyX1NTSEdfQ250LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfSHJfU1NIR19DbnRfRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNwZWVkQXZnX01waAogICAgICAgICAgICAgICAgICAgICAgICAgICApCgpybShBbGxEYXlzX0RpckNoYW5nZSkKc3RyKEFsbERheXNfTmV3T3JkZXIpCgojIFZpZXcoaGVhZChBbGxEYXlzX05ld09yZGVyLCA1MDApKQojIFZpZXcodGFpbChBbGxEYXlzX05ld09yZGVyLCA1MDApKQoKYGBgCgoKU3VtbWFyaXppbmcgdGhlIGRhdGEgdG8gaGVscCBzcG90IGFub21vbGllcy4KYGBge3J9CgpzdW1tYXJ5KEFsbERheXNfTmV3T3JkZXIpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKVmlldyhUcmF2RGlzdE1pX1BjdGlsZXMpOiA5OSUgb2YgVHJhdmVsRGlzdGFuY2VfTWkgYXJlIGFib3V0IDEgbWlsZSBvciBsZXNzLi4uYnV0IHNvbWUgd2VpcmQgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIChlLmcuLCA1ODQgbWlsZXMgdHJhdmVsZWQpIGV4aXN0LgpgYGB7cn0KClRyYXZEaXN0TWlfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShBbGxEYXlzX05ld09yZGVyJFRyYXZlbERpc3RhbmNlX01pKSAlPiUgCiAgbXV0YXRlKCNQY3RpbGUgPSBudGlsZShBbGxEYXlzX05ld09yZGVyJFRyYXZlbERpc3RhbmNlX01pLCAxMDApLAogICAgICAgICAjTWluUiA9IG1pbl9yYW5rKEFsbERheXNfTmV3T3JkZXIkVHJhdmVsRGlzdGFuY2VfTWkpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3T3JkZXIkVHJhdmVsRGlzdGFuY2VfTWkpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoVHJhdkRpc3RNaV9OdGlsZSlbMV0gPC0gIlRyYXZlbERpc3RhbmNlX01pIgojIHN0cihUcmF2RGlzdE1pX050aWxlKQoKVHJhdkRpc3RNaV9OdGlsZV9Sb3dzIDwtIG5yb3coVHJhdkRpc3RNaV9OdGlsZSkKCiMgVmlldyh0YWlsKFRyYXZEaXN0TWlfTnRpbGUsIDUwMCkpCgoKVHJhdkRpc3RNaV9QY3RpbGVzIDwtIGdyb3VwX2J5KFRyYXZEaXN0TWlfTnRpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblRyYXZEaXN0TWlBdFBjdGlsZSA9IG1pbihUcmF2ZWxEaXN0YW5jZV9NaSksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBUcmF2RGlzdE1pX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpCiAgICAgICAgKQoKcm0oVHJhdkRpc3RNaV9OdGlsZSkKcm0oVHJhdkRpc3RNaV9OdGlsZV9Sb3dzKQoKVmlldyhUcmF2RGlzdE1pX1BjdGlsZXMpClRyYXZEaXN0TWlfUGN0aWxlcwoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaS4KCldoeSBhcmUgc29tZSBUcmF2ZWxEaXN0YW5jZV9NaSAiTkEiPyBJdCBsb29rcyBsaWtlIHBhcnRpYWxseSBiZWNhdXNlIHRoZSByZWNvcmRzIGFyZSB0aGUgZmlyc3QgdHJpcCBvZiB0aGUgZGF5IChmb3IgdGhhdCBidXMpLCBzbyBJIHB1cnBvc2VmdWxseSBzZXQgdGhlIGRpc3RhbmNlIHRvICJOQSIuIEFub3RoZXIgcmVhc29uIGlzIGR1ZSB0byB0aGUgb2RvbWV0ZXIgcmVjb3JkaW5nIGEgdmFsdWUgbGVzcyB0aGFuIHRoZSBwcmV2aW91cyBvZG9tZXRlciByZWNvcmRpbmcuIEluIG1vc3QgY2FzZXMsIEkgaGF2ZSBubyBleHBsYW5hdGlvbiBmb3IgdGhpcyAtIHRob3VnaCBJIGhhdmUgb2JzZXJ2ZWQgYWJvdXQgNjclIG9mIGFsbCBpbnN0YW5jZXMgd2hlcmUgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEgKG90aGVyIHRoYW4gYmVjYXVzZSBpdCdzIHRoZSBmaXJzdCByZWNvcmQgb2YgdGhlIGRheSkgYXJlIGluc3RhbmNlcyB3aGVyZSBEaXJDaGFuZ2UyIGlzICJDaGFuZ2UiLiBUaGlzIGlzIHdlaXJkIGFuZCBzaG91bGQgYmUgYXNrZWQgdG8gV01BVEEuCmBgYHtyfQoKIyBWaWV3KGhlYWQoQWxsRGF5c19OZXdPcmRlciwgNTAwKSkKClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICMgV2hlbiBCdXNEYXlfRXZlbnROdW0gPT0gMSwgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEgYnkgZGVzaWduIChkb24ndCB3YW50IHRvIGNhbGN1bGF0ZSBkaXN0YW5jZSBiYXNlZCBvbiB5ZXN0ZXJkYXkncyBwb3NpdGlvbikKICAgICAgICAgICApICU+JSAKICAgICAgIGdyb3VwX2J5KFN0YXJ0U3RvcF9JRCkgJT4lIAogICAgICAgc3VtbWFyaXNlKENudHMgPSBzdW0oaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShkZXNjKENudHMpCiAgICAgICAgICAgICAgKQogICAgKQoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgU3RhcnRTdG9wX0lEID09ICIxMDAwMjQ1LS0xMDAwMjExIgogICAgICAgICAgICkgJT4lIAogICAgICAgc2VsZWN0KFJvd051bV9PRywKICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgRXZlbnRfVGltZSwKICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAsCiAgICAgICAgICAgICAgQnVzX0lELAogICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICBURF9NaV9TU19NZWFuX0YsCiAgICAgICAgICAgICAgVERfTWlfU1NIR19NZWFuLAogICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgIFREX01pX1NTX01lZCwKICAgICAgICAgICAgICBURF9NaV9TU19NZWRfRiwKICAgICAgICAgICAgICBURF9NaV9TU0hHX01lZCwKICAgICAgICAgICAgICBURF9NaV9TU0hHX01lZF9GLAogICAgICAgICAgICAgIFREX01pX1NTX0NudCwKICAgICAgICAgICAgICBURF9NaV9TU19DbnRfRiwKICAgICAgICAgICAgICBURF9NaV9TU0hHX0NudCwKICAgICAgICAgICAgICBURF9NaV9TU0hHX0NudF9GCiAgICAgICAgICAgICAgKSAlPiUgCiAgICAgICBtdXRhdGUoUmF0aW9fTWVhblRvSHZycyA9IFREX01pX1NTX01lYW4gLyBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzKSAlPiUgCiAgICAgICBhcnJhbmdlKEV2ZW50X1RpbWUpCiAgICApCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICApCiAgICApCgojIFRoZXNlIHJlY29yZHMgYXJlIE5BIGJlY3Vhc2UgdGhlIHJlY29yZCBpcyB0aGUgZmlyc3QgcmVjb3JkIG9mIHRoZSBkYXkgKHRoZSBFdmVudF9UaW1lX0RhdGUpClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAzMjYsIDM0NikgfCAjIDMzNgogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA1OTEsIDYxMSkgfCAjIDYwMQogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA4NDUsIDg2NSkgIyA4NTUKICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKVGhlc2UgcmVjb3JkcyBhcmUgTkEgYmVjdWFzZSB0aGUgY3VycmVudCByZWNvcmQgb2RvbWV0ZXIgaXMgbGVzcyB0aGFuIHRoZSBwcmV2aW91cyByZWNvcmQgb2RvbWV0ZXIuIFRoZW9yZXRpY2FsbHksIHRoaXMgc2hvdWxkIE5PVCBoYXBwZW4uIE1lOiBpdCBhcHBlYXJzIHRoYXQgYWJvdXQgNjclIG9mIGFsbCBpbnN0YW5jZXMgd2hlcmUgVHJhdmVsRGlzdGFuY2VfTWkgaXMgTkEgKG90aGVyIHRoYW4gYmVjYXVzZSBpdCdzIHRoIGZpcnN0IHJlY29yZCBvZiB0aGUgZGF5KSBhcmUgaW5zdGFuY2VzIHdoZXJlIERpckNoYW5nZTIgaXMgIkNoYW5nZSIuIFRoaXMgaXMgd2VpcmQgYW5kIHNob3VsZCBiZSBhc2tlZCB0byBXTUFUQS4KYGBge3J9CgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMTk0LCAyMTQpIHwgIyAyMDQKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDQwLCA0NjApIHwgIyA0NTAKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDc4LCA0OTgpIHwgIyA0ODgKICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNTEwLCA1MzApICMgNTIwCiAgICAgICAgICAgKQogICAgKQoKVGVzdFRhYmxlIDwtIGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxCiAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoVHJhdmVsRGlzdGFuY2VfTkEgPSBhcy5mYWN0b3IoaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUcnVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGYWxzZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICApICU+JQogIGdyb3VwX2J5KERpckNoYW5nZTIsIFRyYXZlbERpc3RhbmNlX05BKSAlPiUKICBzdW1tYXJpc2UoVHJhdkRpc3RNaV9OQUNudHMgPSBuKCkKICAgICAgICAgICApCgojIFRlc3RUYWJsZQoKVGVzdFRhYmxlX1NwcmVhZCA8LSBhcy5kYXRhLmZyYW1lKHNwcmVhZChUZXN0VGFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdkRpc3RNaV9OQUNudHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc2VsZWN0KEZhbHNlLAogICAgICAgICBUcnVlCiAgICAgICAgKQoKcm93Lm5hbWVzKFRlc3RUYWJsZV9TcHJlYWQpIDwtIGMoIkNoYW5nZSIsICJTYW1lIikKIyBzdHIoVGVzdFRhYmxlX1NwcmVhZCkKIyBUZXN0VGFibGVfU3ByZWFkCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChUZXN0VGFibGVfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAxCiAgICAgICAgICApCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChUZXN0VGFibGVfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAyCiAgICAgICAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKTGV0J3MgbG9vayBhdCBqdXN0IHRoZSBUcmF2ZWxEaXN0YW5jZV9NaSB2YWx1ZXMgdGhhdCBhcmUgTk9UICJOQSIuCmBgYHtyfQoKcm0oVGVzdFRhYmxlKQpybShUZXN0VGFibGVfU3ByZWFkKQoKVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSA8LSBmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUcmF2ZWxEaXN0YW5jZV9NaSAhPSAwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCmRpbShBbGxEYXlzX05ld09yZGVyKQpkaW0oVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSkKbnJvdyhBbGxEYXlzX05ld09yZGVyKSAtIG5yb3coVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSkKCnN0cihUcmF2ZWxEaXN0YW5jZV9NaV9Ob05BKQpzdW1tYXJ5KFRyYXZlbERpc3RhbmNlX01pX05vTkEpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKTGV0J3MgcGxvdCBqdXN0IHRoZSBUcmF2ZWxEaXN0YW5jZV9NaSB2YWx1ZXMgdGhhdCBhcmUgTk9UICJOQSIuCmBgYHtyfQoKVHJhdkRpc3RNaV9IaXN0RGVuIDwtIGdncGxvdChzZWxlY3QoVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAuLmRlbnNpdHkuLgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4wNSwgZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvdXIgPSAiZ3JleTYwIiwgc2l6ZSA9IDAuMikgKwogIGdlb21fbGluZShzdGF0ID0gImRlbnNpdHkiLCBjb2xvdXIgPSAicmVkIikgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAxLjUpLCB5bGltID0gYygwLCA0LjApCiAgICAgICAgICAgICAgICAgKSArCiAgbGFicyh0aXRsZSA9ICJWYXJpYXRpb24gaW4gRGlzdGFuY2UgQmV0d2VlbiBTdG9wcyIsCiAgICAgICB4ID0gIlRyYXZlbCBEaXN0YW5jZSAobWlsZXMpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIKICAgICAgKQoKVHJhdkRpc3RNaV9IaXN0RGVuCgpgYGAKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkuCgpMb29raW5nIGF0IHRoZSBleHRyZW1lbHkgbGFyZ2UgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzLiBTb21lIChhcHJveCAyNyUpIG9mIFRyYXZlbERpc3RhbmNlX01pIHZhbHVlcyA+IDEgbWlsZSBhcmUgd2hlbiB0aGUgRGlyQ2hhbmdlMiBjaGFuZ2VzLi4uYnV0IHdoYXQgYWJvdXQgdGhlIG90aGVyIH43MyU/CmBgYHtyfQoKcm0oVHJhdmVsRGlzdGFuY2VfTWlfTm9OQSkKCiMgZXhhbXBsZXMgb2Ygd2VpcmRseSBsYXJnZSBUcmF2ZWxEaXN0YW5jZV9NaQpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA+IDEuMTU4NzEyMTIxMiAjIDEuMTU4NzEyMTIxMiBpcyB0aGUgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgICAgKQogICAgKQoKCiMgV2h5IGFyZSB0aGVzZSBleHRyZW1lcz8gIEFpcnBvcnRzPyAgQnVzIGNvbGxlY3Rpb24gcG9pbnRzPwpWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQwNDQsIDQ5NDA2NCkgfCAjIDQ5NDA1NAogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQyNzMsIDQ5NDI5MykgfCAjIDQ5NDI4MwogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQ2MjYsIDQ5NDY0NikgfCAjIDQ5NDYzNgogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAxNjEwMTU2LCAxNjEwMTc2KSB8ICMgMTYxMDE2NgogICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCAyMDczMDc0LCAyMDczMDk0KSAjIDIwNzMwODQKICAgICAgICAgICApCiAgICApCgojIEJlZm9yZSBSZW1vdmluZyBSdW5zCiMgVmlldyhmaWx0ZXIoQWxsRGF5c19Tb3J0ZWQsCiMgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ5NDA0NCwgNDk0MDY0KSB8ICMgNDk0MDU0CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0MjczLCA0OTQyOTMpIHwgIyA0OTQyODMKIyAgICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQ2MjYsIDQ5NDY0NikgfCAjIDQ5NDYzNgojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDE2MTAxNTYsIDE2MTAxNzYpIHwgIyAxNjEwMTY2CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMjA3MzA3NCwgMjA3MzA5NCkgIyAyMDczMDg0CiMgICAgICAgICAgICApCiMgICAgICkKCiMgQWZ0ZXIgUmVtb3ZpbmcgUnVucwojIFZpZXcoZmlsdGVyKEFsbERheXNfRmlyc3RTdG9wSUQsCiMgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDQ5NDA0NCwgNDk0MDY0KSB8ICMgNDk0MDU0CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgNDk0MjczLCA0OTQyOTMpIHwgIyA0OTQyODMKIyAgICAgICAgICAgICAgIGJldHdlZW4oUm93TnVtX09HLCA0OTQ2MjYsIDQ5NDY0NikgfCAjIDQ5NDYzNgojICAgICAgICAgICAgICAgYmV0d2VlbihSb3dOdW1fT0csIDE2MTAxNTYsIDE2MTAxNzYpIHwgIyAxNjEwMTY2CiMgICAgICAgICAgICAgICBiZXR3ZWVuKFJvd051bV9PRywgMjA3MzA3NCwgMjA3MzA5NCkgIyAyMDczMDg0CiMgICAgICAgICAgICApCiMgICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkuCgpBbnkgcmVsYXRpb24gd2l0aCBEaXJDaGFuZ2UyPyAgRG9lc24ndCBsb29rIGFzIGlmIHRoaXMgaXMgc28uCmBgYHtyfQoKRXh0cmVtZVRyYXZEaXN0IDwtIGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkKICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShUcmF2RGlzdF9FeHRyZW1lID0gaWZlbHNlKFRyYXZlbERpc3RhbmNlX01pID4gMS4xNTg3MTIxMjEyLCAjIDEuMTU4NzEyMTIxMiBpcyB0aGUgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRydWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGYWxzZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBncm91cF9ieShEaXJDaGFuZ2UyLCBUcmF2RGlzdF9FeHRyZW1lKSAlPiUgCiAgc3VtbWFyaXNlKFRyYXZEaXN0TUlfRXh0Q250cyA9IG4oKQogICAgICAgICAgICkKCiMgRXh0cmVtZVRyYXZEaXN0CgoKRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCA8LSBhcy5kYXRhLmZyYW1lKHNwcmVhZChFeHRyZW1lVHJhdkRpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdkRpc3RfRXh0cmVtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2RGlzdE1JX0V4dENudHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc2VsZWN0KEZhbHNlLAogICAgICAgICBUcnVlCiAgICAgICAgKQoKcm93Lm5hbWVzKEV4dHJlbWVUcmF2RGlzdF9TcHJlYWQpIDwtIGMoIkNoYW5nZSIsICJTYW1lIikKIyBzdHIoRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCkKIyBFeHRyZW1lVHJhdkRpc3RfU3ByZWFkCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChFeHRyZW1lVHJhdkRpc3RfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAxCiAgICAgICAgICApCgpwcm9wLnRhYmxlKGFzLnRhYmxlKGFzLm1hdHJpeChFeHRyZW1lVHJhdkRpc3RfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAyCiAgICAgICAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pLgoKTG9va2luZyBhdCBzcGVjaWZpYyBidXNlcyBhbmQgU3RhcnRTdG9wX0lELgpgYGB7cn0KCnJtKEV4dHJlbWVUcmF2RGlzdCwgRXh0cmVtZVRyYXZEaXN0X1NwcmVhZCkKClZpZXcoYXJyYW5nZShncm91cF9ieShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAgICAgICAgICAgQnVzX0lECiAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogICAgICAgICAgICAgICBzdW1tYXJpc2UoRGlzdFRyYXZfTWVhbiA9IG1lYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICBEaXN0VHJhdl9NZWQgPSBtZWRpYW4oVHJhdmVsRGlzdGFuY2VfTWksIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgIGRlc2MoRGlzdFRyYXZfTWVkKQogICAgICAgICAgICApCiAgICApCgoKIyBleGFtcGxlIG9mIGV4dHJlbWVseSBzbWFsbCBUcmF2ZWxEaXN0YW5jZV9NaSB2YWx1ZXMgKGxvb2tzIGxpa2UgdGhlIG9kb21ldGVyIHdhc24ndCBmdW5jdGlvbmluZykKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgQnVzX0lEID09IDYxMTEgfAogICAgICAgICAgICAgIEJ1c19JRCA9PSA3MjAxIHwKICAgICAgICAgICAgICBCdXNfSUQgPT0gODA1OAogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShCdXNfSUQsIEV2ZW50X1RpbWUpCiAgICApCgoKVmlldyhhcnJhbmdlKGdyb3VwX2J5KEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQKICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgICAgICAgICAgICAgIHN1bW1hcmlzZShEaXN0VHJhdl9NZWFuID0gbWVhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgICAgICAgIERpc3RUcmF2X01lZCA9IG1lZGlhbihUcmF2ZWxEaXN0YW5jZV9NaSwgbmEucm0gPSBUUlVFKQogICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgZGVzYyhEaXN0VHJhdl9NZWQpCiAgICAgICAgICAgICkKICAgICkKCiMgZXhhbXBsZSBvZiBleHRyZW1lbHkgbGFyZ2UgVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzLi4ubm8gaWRlYSB3aHkuLi4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgU3RhcnRTdG9wX0lEID09ICIxMDAzNjY1LS0xMiIgfAogICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCA9PSAiMTAwMzY2NS0tNTAwMTkyNSIgfAogICAgICAgICAgICAgIFN0YXJ0U3RvcF9JRCA9PSAiMzAwMTAzOC0tMzAwMjU2NSIKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoU3RhcnRTdG9wX0lELCBFdmVudF9UaW1lKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pX05ldy4KCklmIFRyYXZlbERpc250YWNlX01pIGlzIGJlbG93IHRoZSA1dGggcGVyY2VudGlsZSBmb3IgdGhhdCBTdGFydFN0b3BfSUQsIG9yIGlmIFRyYXZlbERpc250YWNlX01pIGlzIGFib3ZlIHRoZSA5NXRoIHBlcmNlbnRpbGUgZm9yIHRoYXQgU3RhcnRTdG9wX0lELCBvciBpZiBUcmF2ZWxEaXN0YW5jZV9NaSBpcyBOQSAod2hlbiB0aGUgQnVzRGF5X0V2ZW50TnVtICE9MSksIGNvbnNpZGVyIHRoaXMgYW4gb3V0bGllci4gIEluIHRoaXMgY2FzZSwgcmVwbGFjZSB0aGUgdmFsdWUgd2l0aCB0aGUgbWVhbiBmb3IgdGhhdCBTdGFydFN0b3BfSUQgYW5kIEhvdXJHcm91cCAoVERfTWlfU1NIR19NZWFuX0YpLCBvciBpZiB0aGVyZSBhcmUgbm90IGVub3VnaCB2YWx1ZXMgYXQgdGhlIEhvdXJHcm91cCBsZXZlbCwgcmVwbGFjZSBpdCB3aXRoIHRoZSBtZWFuIGZvciB0aGF0IFN0YXJ0U3RvcF9JRC4KYGBge3J9CgojIFZpZXcodGFpbChBbGxEYXlzX05ld09yZGVyLCA1MDApKQoKQWxsRGF5c19OZXdUcmF2ZWxEaXN0IDwtIAogIG11dGF0ZShBbGxEYXlzX05ld09yZGVyLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgPSBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWkgPCBURF9NaV9TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiBURF9NaV9TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWkgPCBURF9NaV9TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiBURF9NaV9TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250X0YgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19NZWFuX0YsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxEaXN0YW5jZV9NaSA8IFREX01pX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA+IFREX01pX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfQ250ID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyAhPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyA9PSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NfTWVhbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKSkpLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdfTGFiZWwgPSAKICAgICAgICAgICBmYWN0b3IoaWZlbHNlKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWkgPCBURF9NaV9TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWkgPiBURF9NaV9TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVERfTWlfU1NIR19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJURF9NaV9TU0hHX01lYW5fRiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pIDwgVERfTWlfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gVERfTWlfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTSEdfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX0NudF9GID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgIlREX01pX1NTX01lYW5fRiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbERpc3RhbmNlX01pIDwgVERfTWlfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gVERfTWlfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFREX01pX1NTX0NudF9GIDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBURF9NaV9TU19DbnQgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVERfTWlfU1NfTWVhbiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZShpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaSkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgIT0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzIiwKICAgICAgICAgICAgICAgICAgaWZlbHNlKGlzLm5hKFRyYXZlbERpc3RhbmNlX01pKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEJ1c0RheV9FdmVudE51bSAhPSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyA9PSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgIlREX01pX1NTX01lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgIlRyYXZlbERpc3RhbmNlX01pIgogICAgICAgICAgICAgICAgICAgICAgICApKSkpKQogICAgICAgICAgICAgICAgICksCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMgPSBpZmVsc2UoIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX0h2cnMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgIT0gMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsRGlzdGFuY2VfTWlfTmV3IDwgVERfTWlfcTIgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3ID4gVERfTWlfcTk4CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzX0xhYmVsID0KICAgICAgICAgICBmYWN0b3IoaWZlbHNlKCFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgIT0gMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxEaXN0YW5jZV9NaV9OZXcgPCBURF9NaV9xMiB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IFREX01pX3E5OAogICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgIlRyYXZlbERpc3RhbmNlX01pX0h2cnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKFRyYXZlbERpc3RhbmNlX01pX05ld19MYWJlbCkKICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICksCiAgICAgICAgIFNwZWVkQXZnX01waF9OZXdIdnJzID0gVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyAvIFRyYXZlbFRpbWVfSHIKICAgICAgICApCgpzdHIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0KQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pX0h2cnMgJiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcuCgpRdWljayBzdW1tYXJ5IGFuZCB0aGVuIGNvcnJlbGF0aW9uIGNhbGN1bGF0aW9uLgpgYGB7cn0KCnJtKEFsbERheXNfTmV3T3JkZXIpCgoKIyAzOCByb3dzIG1lZXQgdGhpcyBjcml0ZXJpYSBhbnltb3JlICAtLSAgYXBwZWFycyB0byBiZSB0aGUgY2FzZSB3aGVuIGJvdGggdGhlIExhdCBMb25nIGNhbGN1bGF0aW9ucywgYW5kIHRoZSBUcmF2ZWxEaXN0YW5jZSBjYWxjdWxhdGlvbnMgZGlkIG5vdCBmdW5jdGlvbiBwcm9wZXJseS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICBpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpICYKICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICkKICAgICkKClZpZXcoQWxsRGF5c19OZXdUcmF2ZWxEaXN0ICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxEaXN0YW5jZV9NaV9OZXcpKSAlPiUgCiAgICAgICBoZWFkKDUwMCkKICAgICkKCnN1bW1hcnkoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICkKICAgICAgICkKCnN1bW1hcnkoc2VsZWN0KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzCiAgICAgICAgICAgICAgKQogICAgICAgKQoKCmNvcihzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pLAogICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LAogICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICksCiAgICB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIgogICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZyc19MYWJlbCAmIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwuCgpTaG93IGhvdyB0aGUgbGFiZWxzIGNoYW5nZWQuCmBgYHtyfQoKZ3JvdXBfYnkoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdfTGFiZWwsCiAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwKICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoQ250TnVtID0gbigpLAogICAgICAgICAgICBDbnRQY3QgPSBmb3JtYXQoQ250TnVtIC8gbnJvdyhBbGxEYXlzX05ld1RyYXZlbERpc3QpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NpZW50aWZpYyA9IDk5OTkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICkgJT4lIAogIGFycmFuZ2UoZGVzYyhDbnRQY3QpCiAgICAgICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWkgJiBUcmF2ZWxEaXN0YW5jZV9NaV9IdnJzICYgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LgoKR3JhcGhpbmcgdGhlIHR3byBtZXRob2RzIG9mIGNhbGN1bGF0aW5nIFRyYXZlbERpc3RhbmNlX01pLgoKRmlyc3QsIGxldCdzIGdldCBjcmVhdGUgYSBmdW5jdGlvbiB0byBwbG90IHRoZSBsaW5lciBtb2RlbCBlcXVhdGlvbi4KYGBge3J9CgpsbV9lcW4gPC0gZnVuY3Rpb24oZGYsIHksIHgpewogIG0gPC0gbG0oeSB+IHgsIGRmKQogIAogIGwgPC0gbGlzdChhID0gZm9ybWF0KGNvZWYobSlbMV0sIGRpZ2l0cyA9IDIpLAogICAgICAgICAgICBiID0gZm9ybWF0KGFicyhjb2VmKG0pWzJdKSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgIHMxID0gaWZlbHNlKHRlc3QgPSBjb2VmKG0pWzJdID4gMCwKICAgICAgICAgICAgICAgICAgICAgICAgeWVzID0gIisiLAogICAgICAgICAgICAgICAgICAgICAgICBubyA9ICItIgogICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIHIyID0gZm9ybWF0KHN1bW1hcnkobSkkci5zcXVhcmVkLAogICAgICAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAzCiAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICkKICAKICBlcSA8LSBzdWJzdGl0dXRlKGl0YWxpYyh5KSA9PSBhfn5zMX5+YiAlLiUgaXRhbGljKHgpKiIsIn5+aXRhbGljKHIpXjJ+Ij0ifnIyLAogICAgICAgICAgICAgICAgICAgbAogICAgICAgICAgICAgICAgICApCiAgCiAgYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpCiAgICAgICAgICAgICAgKSAgICAgICAgICAgICAKfQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaSAmIFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMuCgpTY2F0dGVyIHBsb3QgKHVzaW5nIGEgMTAlIHNhbXBsZSB0byBtYWtpbmcgcGxvdHRpbmcgdGltZSBmYXN0ZXIgYW5kIHRvIHJlZHVjZSB1bi1uZWVkZWQgZGF0YSBpbiB0aGUgInNhbWUiIHNwbG90KS4KYGBge3J9CgpzZXQuc2VlZCgxMjM0NTY3ODkpCkFsbERheXNfTmV3VHJhdmVsRGlzdF8xMFBjdCA8LSBmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhaXMubmEoVHJhdmVsRGlzdGFuY2VfTWkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICByZW5hbWUoRGlzdE1ldGhvZCA9IFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnNfTGFiZWwpICU+JSAKICBzYW1wbGVfZnJhYygwLjEpCgoKVHJhdkRpc3RfTWlWc0NhbGMgPC0gZ2dwbG90KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3RfMTBQY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaXN0TWV0aG9kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBEaXN0TWV0aG9kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygicmVkIiwiYmx1ZSIsICJncmVlbiIsICJvcmFuZ2UiLCAiYmxhY2siKQogICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9zaGFwZShzb2xpZCA9IEZBTFNFKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gImJsdWUiKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLCBjb2xvdXIgPSAicmVkIikgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAxLjUpLCB5bGltID0gYygwLCAxLjUpCiAgICAgICAgICAgICAgICAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxLjUsIDAuMjUpCiAgICAgICAgICAgICAgICAgICAgKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAxLjUsIDAuMjUpCiAgICAgICAgICAgICAgICAgICAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsICNjKDAuODUsIDAuNDApLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KQogICAgICAgKSArCiAgYW5ub3RhdGUobGFiZWwgPSBsbV9lcW4oZGYgPSBBbGxEYXlzX05ld1RyYXZlbERpc3RfMTBQY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IEFsbERheXNfTmV3VHJhdmVsRGlzdF8xMFBjdCRUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0JFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMKICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIyB4ID0gNjIsCiAgICAgICAgICAgIyB5ID0gMjAsCiAgICAgICAgICAgeCA9IDAuNzAsCiAgICAgICAgICAgeSA9IDAuMDAsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAiYmx1ZSIsCiAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICBhbm5vdGF0ZShsYWJlbCA9ICJSZWZlcmVuY2UgTGluZSAoc2xvcGUgPSAxKSIsCiAgICAgICAgICAgIyB4ID0gMTYsCiAgICAgICAgICAgIyB5ID0gMzAsCiAgICAgICAgICAgeCA9IDAuODAsCiAgICAgICAgICAgeSA9IDEuMDUsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAicmVkIgogICAgICAgICAgKSArCiAgbGFicyh0aXRsZSA9ICJUcmF2ZWxEaXN0YW5jZV9NaSB2cy4gVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyIsCiAgICAgICB4ID0gIlRyYXZlbERpc3RhbmNlX01pIiwKICAgICAgIHkgPSAiVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyIKICAgICAgKQojICsKIyAgIGdlb21faml0dGVyKCkKClRyYXZEaXN0X01pVnNDYWxjCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbERpc3RhbmNlX01pICYgVHJhdmVsRGlzdGFuY2VfTWlfSHZycyAmIFRyYXZlbERpc3RhbmNlX01pX05ldy4KCkdyYXBoaW5nIHRlc3Qgd2l0aCByYm9rZWguCmBgYHtyfQoKVHJhdkRpc3RfTWlWc0NhbGNfQm9rZWggPC0gZmlndXJlKGRhdGEgPSBzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlzdE1ldGhvZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bGltID0gYygwLCAxLjUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWxpbSA9IGMoMCwgMS41KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZF9sb2NhdGlvbiA9ICJib3R0b21fcmlnaHQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIGx5X3BvaW50cyh4ID0gVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgIHkgPSBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLAogICAgICAgICAgICBjb2xvciA9IERpc3RNZXRob2QsCiAgICAgICAgICAgIGhvdmVyID0gYyhUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLCBUcmF2ZWxEaXN0YW5jZV9NaSwgRGlzdE1ldGhvZCkKICAgICAgICAgICApICU+JSAKICBseV9hYmxpbmUoYSA9IDAsIGIgPSAxLCBjb2xvciA9ICJyZWQiKQoKVHJhdkRpc3RfTWlWc0NhbGNfQm9rZWgKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LgoKQ2FsY3VsYXRpbmcgdGhlIG1pbmltdW0gVHJhdmVsRGlzdGFuY2VfTWlfTmV3IHZhbHVlIGF0IGVhY2ggcGVyY2VudGlsZS4KYGBge3J9CgpybShUcmF2RGlzdF9NaVZzQ2FsY19Cb2tlaCkKcm0oQWxsRGF5c19OZXdUcmF2ZWxEaXN0XzEwUGN0KQoKCnN1bW1hcnkoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWksCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX0h2cnMsCiAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICkKICAgICAgICkKCnN1bW1hcnkoc2VsZWN0KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICAgICAgICAgICBCdXNEYXlfRXZlbnROdW0gIT0gMQogICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSwKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfSHZycywKICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3LAogICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzCiAgICAgICAgICAgICAgKQogICAgICAgKQoKClRyYXZEaXN0TWlOX050aWxlIDwtIGFzLmRhdGEuZnJhbWUoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3RhcnRTdG9wX0lELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdfTGFiZWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZyc19MYWJlbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZShQY3RSX04gPSBwZXJjZW50X3JhbmsoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFRyYXZlbERpc3RhbmNlX01pX05ldyksCiAgICAgICAgICMgUGN0Ul9IID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSwKICAgICAgICAgUGN0Ul9Sb3VuZF9OID0gcm91bmQoUGN0Ul9OLCAyKQogICAgICAgICAjIFBjdFJfUm91bmRfSCA9IHJvdW5kKFBjdFJfSCwgMikKICAgICAgICApIAoKIyBzdHIoVHJhdkRpc3RNaU5fTnRpbGUpCiMgVmlldyhoZWFkKFRyYXZEaXN0TWlOX050aWxlLCA1MDApKQoKVHJhdkRpc3RNaU5fTnRpbGVfUm93cyA8LSBucm93KFRyYXZEaXN0TWlOX050aWxlKQoKIyBWaWV3KHRhaWwoVHJhdkRpc3RNaU5fTnRpbGUsIDUwMCkpCgoKVHJhdkRpc3RNaU5fUGN0aWxlcyA8LSBncm91cF9ieShUcmF2RGlzdE1pTl9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kX04KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblRETWlBdFBjdGlsZV9OID0gbWluKFRyYXZlbERpc3RhbmNlX01pX05ldyksCiAgICAjIE1pblRETWlBdFBjdGlsZV9IID0gbWluKFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMpLAogICAgQ250c0F0UGN0aWxlX04gPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX05ldykpLAogICAgIyBDbnRzQXRQY3RpbGVfSCA9IHN1bSghaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykpLAogICAgUGN0c0F0UGN0aWxlX04gPSBDbnRzQXRQY3RpbGVfTiAvIFRyYXZEaXN0TWlOX050aWxlX1Jvd3MKICAgICMgUGN0c0F0UGN0aWxlX0ggPSBDbnRzQXRQY3RpbGVfSCAvIFRyYXZEaXN0TWlOX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UF9OID0gY3Vtc3VtKFBjdHNBdFBjdGlsZV9OKQogICAgICAgICAjIEN1bVN1bVBBdFBfSCA9IGN1bXN1bShQY3RzQXRQY3RpbGVfSCkKICAgICAgICApCgojIFZpZXcoVHJhdkRpc3RNaU5fUGN0aWxlcykKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwoKQ2FsY3VsYXRpbmcgdGhlIG1pbmltdW0gVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyB2YWx1ZSBhdCBlYWNoIHBlcmNlbnRpbGUuCmBgYHtyfQoKVHJhdkRpc3RNaUhfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdGFydFN0b3BfSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWlfTmV3X0xhYmVsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzX0xhYmVsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbERpc3RhbmNlX01pX05ldywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIG11dGF0ZSgjIFBjdFJfTiA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsRGlzdGFuY2VfTWlfTmV3KSwKICAgICAgICAgUGN0Ul9IID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSwKICAgICAgICAgIyBQY3RSX1JvdW5kX04gPSByb3VuZChQY3RSX04sIDIpLAogICAgICAgICBQY3RSX1JvdW5kX0ggPSByb3VuZChQY3RSX0gsIDIpCiAgICAgICAgKSAKCiMgc3RyKFRyYXZEaXN0TWlIX050aWxlKQojIFZpZXcoaGVhZChUcmF2RGlzdE1pSF9OdGlsZSwgNTAwKSkKClRyYXZEaXN0TWlIX050aWxlX1Jvd3MgPC0gbnJvdyhUcmF2RGlzdE1pSF9OdGlsZSkKCiMgVmlldyh0YWlsKFRyYXZEaXN0TWlIX050aWxlLCA1MDApKQoKClRyYXZEaXN0TWlIX1BjdGlsZXMgPC0gZ3JvdXBfYnkoVHJhdkRpc3RNaUhfTnRpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGN0Ul9Sb3VuZF9ICiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICAjIE1pblRETWlBdFBjdGlsZV9OID0gbWluKFRyYXZlbERpc3RhbmNlX01pX05ldyksCiAgICBNaW5URE1pQXRQY3RpbGVfSCA9IG1pbihUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSwKICAgICMgQ250c0F0UGN0aWxlX04gPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX05ldykpLAogICAgQ250c0F0UGN0aWxlX0ggPSBzdW0oIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMpKSwKICAgICMgUGN0c0F0UGN0aWxlX04gPSBDbnRzQXRQY3RpbGVfTiAvIFRyYXZEaXN0TWlIX050aWxlX1Jvd3MsCiAgICBQY3RzQXRQY3RpbGVfSCA9IENudHNBdFBjdGlsZV9IIC8gVHJhdkRpc3RNaUhfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZSgjIEN1bVN1bVBBdFBfTiA9IGN1bXN1bShQY3RzQXRQY3RpbGVfTiksCiAgICAgICAgIEN1bVN1bVBBdFBfSCA9IGN1bXN1bShQY3RzQXRQY3RpbGVfSCkKICAgICAgICApCgojIFZpZXcoVHJhdkRpc3RNaUhfUGN0aWxlcykKCmBgYAoKCkpvaW4gVHJhdkRpc3RNaUhfUGN0aWxlcywgVHJhdkRpc3RNaU5fUGN0aWxlcywgYW5kIFRyYXZEaXN0TWlfUGN0aWxlcy4KCn4xMSUgb2YgcmlkZXMgYXJlIHN0aWxsIHNob3dpbmcgYXMgbGVzcyB0aGFuIDAuMSBtaWxlcyBvZiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzLgpgYGB7cn0KCnJtKFRyYXZEaXN0TWlOX050aWxlX1Jvd3MsIFRyYXZEaXN0TWlIX050aWxlX1Jvd3MsIFRyYXZEaXN0TWlOX050aWxlLCBUcmF2RGlzdE1pSF9OdGlsZSkKCgojIFZpZXcoVHJhdkRpc3RNaV9QY3RpbGVzKQojIFZpZXcoVHJhdkRpc3RNaU5fUGN0aWxlcykKIyBWaWV3KFRyYXZEaXN0TWlIX1BjdGlsZXMpCgpUcmF2RGlzdE1pX1BjdGlsZXNfQWxsIDwtIGlubmVyX2pvaW4oeCA9IFRyYXZEaXN0TWlfUGN0aWxlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBUcmF2RGlzdE1pTl9QY3RpbGVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCJQY3RSX1JvdW5kIiA9ICJQY3RSX1JvdW5kX04iKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBpbm5lcl9qb2luKHkgPSBUcmF2RGlzdE1pSF9QY3RpbGVzLAogICAgICAgICAgICAgYnkgPSBjKCJQY3RSX1JvdW5kIiA9ICJQY3RSX1JvdW5kX0giKQogICAgICAgICAgICApICU+JSAKICBzZWxlY3QoUGN0Ul9Sb3VuZCwKICAgICAgICAgTWluVHJhdkRpc3RNaUF0UGN0aWxlLAogICAgICAgICBNaW5URE1pQXRQY3RpbGVfTiwKICAgICAgICAgTWluVERNaUF0UGN0aWxlX0gsCiAgICAgICAgIENudHNBdFBjdGlsZSwKICAgICAgICAgQ250c0F0UGN0aWxlX04sCiAgICAgICAgIENudHNBdFBjdGlsZV9ILAogICAgICAgICBQY3RzQXRQY3RpbGUsCiAgICAgICAgIFBjdHNBdFBjdGlsZV9OLAogICAgICAgICBQY3RzQXRQY3RpbGVfSCwKICAgICAgICAgQ3VtU3VtUEF0UCwKICAgICAgICAgQ3VtU3VtUEF0UF9OLAogICAgICAgICBDdW1TdW1QQXRQX0gKICAgICAgICAgKQoKIyBzdHIoVHJhdkRpc3RNaV9QY3RpbGVzX0FsbCkKCnJtKFRyYXZEaXN0TWlfUGN0aWxlcywgVHJhdkRpc3RNaU5fUGN0aWxlcyxUcmF2RGlzdE1pSF9QY3RpbGVzKQoKClZpZXcoVHJhdkRpc3RNaV9QY3RpbGVzX0FsbCkKVHJhdkRpc3RNaV9QY3RpbGVzX0FsbAoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxEaXN0YW5jZV9NaV9OZXcuCgpXaHkgYXJlIHRoZXJlIHN0aWxsIHNvbWUgc21hbGwgb3IgbGFyZ2UgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyB2YWx1ZXMuCmBgYHtyfQoKIyBWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiMgICAgICAgICAgICAgIWlzLm5hKFRyYXZlbERpc3RhbmNlX01pX05ld0h2cnMpCiMgICAgICAgICAgICApICU+JSAKIyAgICAgICAgc2VsZWN0KC1URF9NaV9xMiwKIyAgICAgICAgICAgICAgIC1URF9NaV9xOTgsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NfcTUsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NfcTk1LAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfcTUsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NIR19xOTUsCiMgICAgICAgICAgICAgICAtVERfTWlfTWVhbiwKIyAgICAgICAgICAgICAgIC1URF9NaV9NZWFuX0YsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NfTWVhbiwKIyAgICAgICAgICAgICAgIC1URF9NaV9TU19NZWFuX0YsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NIR19NZWFuLAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfTWVhbl9GLAojICAgICAgICAgICAgICAgLVREX01pX01lZCwKIyAgICAgICAgICAgICAgIC1URF9NaV9NZWRfRiwKIyAgICAgICAgICAgICAgIC1URF9NaV9TU19NZWQsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NfTWVkX0YsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NIR19NZWQsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NIR19NZWRfRiwKIyAgICAgICAgICAgICAgIC1URF9NaV9DbnQsCiMgICAgICAgICAgICAgICAtVERfTWlfQ250X0YsCiMgICAgICAgICAgICAgICAtVERfTWlfU1NfQ250LAojICAgICAgICAgICAgICAgLVREX01pX1NTX0NudF9GLAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfQ250LAojICAgICAgICAgICAgICAgLVREX01pX1NTSEdfQ250X0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX3EyLAojICAgICAgICAgICAgICAgLVRUX1NlY19xOTgsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTX3E1LAojICAgICAgICAgICAgICAgLVRUX1NlY19TU19xOTUsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTSEdfcTUsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTSEdfcTk1LAojICAgICAgICAgICAgICAgLVRUX1NlY19NZWFuLAojICAgICAgICAgICAgICAgLVRUX1NlY19NZWFuX0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTX01lYW4sCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTX01lYW5fRiwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NIR19NZWFuLAojICAgICAgICAgICAgICAgLVRUX1NlY19TU0hHX01lYW5fRiwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfTWVkLAojICAgICAgICAgICAgICAgLVRUX1NlY19NZWRfRiwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NfTWVkLAojICAgICAgICAgICAgICAgLVRUX1NlY19TU19NZWRfRiwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NIR19NZWQsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTSEdfTWVkX0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX0NudCwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfQ250X0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTX0NudCwKIyAgICAgICAgICAgICAgIC1UVF9TZWNfU1NfQ250X0YsCiMgICAgICAgICAgICAgICAtVFRfU2VjX1NTSEdfQ250LAojICAgICAgICAgICAgICAgLVRUX1NlY19TU0hHX0NudF9GLAojICAgICAgICAgICAgICAgLVRUX0hyX3EyLAojICAgICAgICAgICAgICAgLVRUX0hyX3E5OCwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU19xNSwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU19xOTUsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19xNSwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU0hHX3E5NSwKIyAgICAgICAgICAgICAgIC1UVF9Icl9NZWFuLAojICAgICAgICAgICAgICAgLVRUX0hyX01lYW5fRiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU19NZWFuLAojICAgICAgICAgICAgICAgLVRUX0hyX1NTX01lYW5fRiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU0hHX01lYW4sCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19NZWFuX0YsCiMgICAgICAgICAgICAgICAtVFRfSHJfTWVkLAojICAgICAgICAgICAgICAgLVRUX0hyX01lZF9GLAojICAgICAgICAgICAgICAgLVRUX0hyX1NTX01lZCwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU19NZWRfRiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU0hHX01lZCwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU0hHX01lZF9GLAojICAgICAgICAgICAgICAgLVRUX0hyX0NudCwKIyAgICAgICAgICAgICAgIC1UVF9Icl9DbnRfRiwKIyAgICAgICAgICAgICAgIC1UVF9Icl9TU19DbnQsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NfQ250X0YsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19DbnQsCiMgICAgICAgICAgICAgICAtVFRfSHJfU1NIR19DbnRfRgojICAgICAgICAgICAgICApICU+JSAKIyAgICAgICAgYXJyYW5nZShUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSAlPiUgCiMgICAgICAgIGhlYWQoNTAwKQojICAgICApCgpWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgICFpcy5uYShUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKQogICAgICAgICAgICkgJT4lIAogICAgICAgc2VsZWN0KC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKSAlPiUKICAgICAgIGhlYWQoNTAwKQogICAgKQoKIyBleGFtcGxlcyBvZiB0aGUgc21hbGxlc3QgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyB2YWx1ZXMuClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNDI0NDQwICYgUm93TnVtX09HIDw9IDE0MjQ0NjApIHwgIyAxNDI0NDUwICAtLSAgZGlyZWN0aW9uIGNoYW5nZQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA3NjMyOTIgJiBSb3dOdW1fT0cgPD0gNzYzMzEyKSB8ICMgNzYzMzAyICAtLSAgZGlyZWN0aW9uIGNoYW5nZQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjc5MDkzICYgUm93TnVtX09HIDw9IDE2NzkxMTMpIHwgIyAxNjc5MTAzICAtLSAgZGlyZWN0aW9uIGNoYW5nZQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyODYwOTE4ICYgUm93TnVtX09HIDw9IDI4NjA5MzgpICMgMjg2MDkyOCAgLS0gIGxvb2tzIGNvcnJlY3QKICAgICAgICAgICApICU+JSAKICAgICAgIHNlbGVjdCgtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgICApCiAgICApCgoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAhaXMubmEoVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycykKICAgICAgICAgICApICU+JSAKICAgICAgIHNlbGVjdCgtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxEaXN0YW5jZV9NaV9OZXdIdnJzKQogICAgICAgICAgICAgICkgJT4lCiAgICAgICBoZWFkKDUwMCkKICAgICkKCiMgZXhhbXBsZXMgb2YgdGhlIGxhcmdlc3QgVHJhdmVsRGlzdGFuY2VfTWlfTmV3SHZycyB2YWx1ZXMuClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxMDkyMDAwICYgUm93TnVtX09HIDw9IDEwOTIwNTApIHwgIyAxMDkyMDMwICAtLSAgZGlyZWN0aW9uIGNoYW5nZQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjA5NDYwICYgUm93TnVtX09HIDw9IDE2MDk0ODApIHwgIyAxNjA5NDcwICAtLSBkaXJlY3Rpb24gY2hhbmdlIAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA1MDg5MDQgJiBSb3dOdW1fT0cgPD0gNTA4OTI0KSB8ICMgNTA4OTE0ICAtLSAgZGlyZWN0aW9uIGNoYW5nZSAmIG9yaWdpbmFsIFN0b3BJRCB3YXMgYmFkCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDI0NzYzNDUgJiBSb3dOdW1fT0cgPD0gMjQ3NjM2NSkgIyAyNDc2MzU1ICAtLSAgZGlyZWN0aW9uIGNoYW5nZQogICAgICAgICAgICkgJT4lIAogICAgICAgc2VsZWN0KC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICAgICkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9Ici4KClZpZXcoVHJhdkRpc3RNaV9QY3RpbGVzKTogOTglIG9mIFRyYXZlbFRpbWVfSHIgYXJlIGJldHdlZW4gNyBzZWNvbmRzIGFuZCA0NjQgc2Vjb25kcyAofjggbWludXRlcykuCmBgYHtyfQoKVHJhdlRpbWVIcl9OdGlsZSA8LSBzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX0hyCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKCMgUGN0aWxlID0gbnRpbGUoQWxsRGF5c19OZXdUcmF2ZWxEaXN0JFRyYXZlbFRpbWVfSHIsIDEwMCksCiAgICAgICAgICMgTWluUiA9IG1pbl9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxUaW1lX0hyKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkVHJhdmVsVGltZV9IciksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgojIHN0cihUcmF2VGltZUhyX050aWxlKQoKVHJhdlRpbWVIcl9OdGlsZV9Sb3dzIDwtIG5yb3coVHJhdlRpbWVIcl9OdGlsZSkKCiMgVmlldyh0YWlsKFRyYXZUaW1lSHJfTnRpbGUsIDUwMCkpCgoKVHJhdlRpbWVIcl9QY3RpbGVzIDwtIGdyb3VwX2J5KFRyYXZUaW1lSHJfTnRpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblRyYXZUaW1lSHJBdFBjdGlsZSA9IG1pbihUcmF2ZWxUaW1lX0hyKSwKICAgIENudHNBdFBjdGlsZSA9IG4oKSwKICAgIFBjdHNBdFBjdGlsZSA9IENudHNBdFBjdGlsZSAvIFRyYXZUaW1lSHJfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSksCiAgICAgICAgIE1pblRyYXZUaW1lU2VjQXRQY3RpbGUgPSBNaW5UcmF2VGltZUhyQXRQY3RpbGUgKiAzNjAwCiAgICAgICAgKQoKcm0oVHJhdlRpbWVIcl9OdGlsZV9Sb3dzKQpybShUcmF2VGltZUhyX050aWxlKQpWaWV3KFRyYXZUaW1lSHJfUGN0aWxlcykKVHJhdlRpbWVIcl9QY3RpbGVzCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbFRpbWVfSHIuCgpIaXN0b2dyYW0gb2YgVHJhdmVsVGltZV9TZWMuCmBgYHtyfQoKVHJhdlRpbWVfU2VjX0hpc3REZW4gPC0gZ2dwbG90KGZpbHRlcihzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIWlzLm5hKFRyYXZlbFRpbWVfU2VjKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVHJhdmVsVGltZV9TZWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IC4uZGVuc2l0eS4uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSA1LCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAiZGVuc2l0eSIsIGNvbG91ciA9ICJyZWQiKSArCiAgIyBzdGF0X2JpbihiaW53aWR0aCA9IDUsCiAgIyAgICAgICAgICBnZW9tID0gInRleHQiLAogICMgICAgICAgICAgc2l6ZSA9IDIuNSwKICAjICAgICAgICAgIHZqdXN0ID0gMS41LAogICMgICAgICAgICAgYWVzKGxhYmVsID0gZm9ybWF0KC4uY291bnQuLiwgYmlnLm1hcmsgPSAiLCIpCiAgIyAgICAgICAgICAgICApLAogICMgICAgICAgICApICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMTgwKSwgeWxpbSA9IGMoMCwgMC4wMikKICAgICAgICAgICAgICAgICApICsKICAjICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJWYXJpYXRpb24gaW4gVHJhdmVsIFRpbWUiLAogICAgICAgeCA9ICJUcmF2ZWwgVGltZSAoc2VjKSIsCiAgICAgICB5ID0gIkRlbnNpdHkiCiAgICAgICkKClRyYXZUaW1lX1NlY19IaXN0RGVuCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbFRpbWVfU2VjLgoKVHJhdmVsVGltZV9TZWMgdmFsdWVzIGFyZSBOQS4KYGBge3J9CgpzdW1tYXJ5KEFsbERheXNfTmV3VHJhdmVsRGlzdCRUcmF2ZWxUaW1lX1NlYykKCgpWaWV3KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICApICU+JSAKICAgICAgIGZpbHRlcihpcy5uYShUcmF2ZWxUaW1lX1NlYykgJgogICAgICAgICAgICAgICAgQnVzRGF5X0V2ZW50TnVtICE9IDEgICMgVHJhdmVsVGltZSBwdXJwb3NlZnVsbHkgbm90IGNhbGN1bGF0ZWQgaGVyZQogICAgICAgICAgICAgKQogICAgKQoKIyBleGFtcGxlcyBvZiBUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMgdGhhdCBhcmUgTkEuIFRoZXNlIGFyZSBOQSBiZWNhdXNlIHRoZSBFdmVudF9UaW1lICYgRGVwYXJ0dXJlX1RpbWUgcmVhZGluZ3MgYXJlIG5vdCBhY2N1cmF0ZSAoaS5lLiwgdGhlIHByZXZpb3VzIERlcGFydHVyZV9UaW1lIGlzIEJFRk9SRSBvciBFUVVBTCBUTyB0aGUgY3VycmVudCBFdmVudF9UaW1lKS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDkwODA5ICYgUm93TnVtX09HIDw9IDkwODI5KSB8ICMgOTA4MTkKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gOTA4ODEgJiBSb3dOdW1fT0cgPD0gOTA5MDEpIHwgIyA5MDg5MQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyNTk3MDY2ICYgUm93TnVtX09HIDw9IDI1OTcwODYpIHwgIyAyNTk3MDc2CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDI2MTMzMDUgJiBSb3dOdW1fT0cgPD0gMjYxMzMyNSkgIyAyNjEzMzE1CiAgICAgICAgICAgKSAlPiUgCiAgICAgICBzZWxlY3QoLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKSkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9TZWMuCgpUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMgYXJlIGV4dHJlbWVseSBzbWFsbC4KYGBge3J9CgpWaWV3KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICApICU+JSAKICAgICAgIGZpbHRlcighaXMubmEoVHJhdmVsVGltZV9TZWMpCiAgICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoVHJhdmVsVGltZV9TZWMsCiAgICAgICAgICAgICAgIGRlc2MoU3BlZWRBdmdfTXBoX05ld0h2cnMpCiAgICAgICAgICAgICAgKSAlPiUKICAgICAgIGhlYWQoNTAwKQogICAgKQoKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyBzbWFsbCAoMSBzZWMpIGFuZCBTcGVlZEF2Z19NcGhfTmV3SHZycyBpcyBsYXJnZS4KVmlldyhzZWxlY3QoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBmaWx0ZXIoKFJvd051bV9PRyA+PSAyMjE3MzUzICYgUm93TnVtX09HIDw9IDIyMTczNzMpIHwgIyAyMjE3MzYzCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDMwOTAzMjEgJiBSb3dOdW1fT0cgPD0gMzA5MDM0MSkgfCAjIDMwOTAzMzEKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gODA3NjQgJiBSb3dOdW1fT0cgPD0gODA3ODQpIHwgIyA4MDc3NAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMzg0MCAmIFJvd051bV9PRyA8PSAzMzg2MCkgIyAzMzg1MAogICAgICAgICAgICkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgVHJhdmVsVGltZV9TZWMuCgpUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMgYXJlIGV4dHJlbWVseSBsYXJnZS4KYGBge3J9CgpWaWV3KHNlbGVjdChBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICApICU+JSAKICAgICAgIGZpbHRlcighaXMubmEoVHJhdmVsVGltZV9TZWMpCiAgICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxUaW1lX1NlYyksCiAgICAgICAgICAgICAgIFNwZWVkQXZnX01waF9OZXdIdnJzCiAgICAgICAgICAgICAgKSAlPiUKICAgICAgIGhlYWQoNTAwKQogICAgKQoKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyBsYXJnZSBhbmQgU3BlZWRBdmdfTXBoX05ld0h2cnMgaXMgc21hbGwuClZpZXcoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgICkgJT4lIAogICAgICAgZmlsdGVyKChSb3dOdW1fT0cgPj0gMTAwNzcwMyAmIFJvd051bV9PRyA8PSAxMDA3NzIzKSB8ICMgMTAwNzcxMwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyMzczNTY0ICYgUm93TnVtX09HIDw9IDIzNzM1ODQpIHwgIyAyMzczNTc0CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDg2NDM3OSAmIFJvd051bV9PRyA8PSA4NjQzOTkpIHwgIyA4NjQzODkKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjU3MDA2MCAmIFJvd051bV9PRyA8PSAyNTcwMDgwKSAjIDI1NzAwNzAKICAgICAgICAgICApCiAgICApCgoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBUcmF2ZWxUaW1lX1NlYy4KCkFyZSBsYXJnZSBUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMgcmVsYXRlZCB0byBSb3V0ZUNoYW5nZXMuCmBgYHtyfQoKVFRMYXJnZVJ0ZUNobmcgPC0gc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgbXV0YXRlKFRUX091dCA9IGZhY3RvcihpZmVsc2UoVHJhdmVsVGltZV9TZWMgPiA0NjQsICAjIHRoaXMgaXMgdGhlIDk5dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPdXRsaWVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9ybWFsIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgKQoKIyBzdHIoVFRMYXJnZVJ0ZUNobmcpCgoKVFRMYXJnZVJ0ZUNobmdfQ250cyA8LSBncm91cF9ieShUVExhcmdlUnRlQ2huZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSdGVDaGFuZ2UyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX091dAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKENudHMgPSBuKCkKICAgICAgICAgICApCgpUVExhcmdlUnRlQ2huZ19TcHJlYWQgPC0gYXMuZGF0YS5mcmFtZShzcHJlYWQoVFRMYXJnZVJ0ZUNobmdfQ250cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX091dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENudHMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lCiAgc2VsZWN0KC1SdGVDaGFuZ2UyKQoKcm93Lm5hbWVzKFRUTGFyZ2VSdGVDaG5nX1NwcmVhZCkgPC0gYygiQ2hhbmdlIiwgIlNhbWUiKQojIHN0cihUVExhcmdlUnRlQ2huZ19TcHJlYWQpCgoKIyBXaGVuIHRoZSBCdXMgaW52b2x2ZXMgYSBSb3V0ZSAiY2hhbmdlIiwgdGhlcmUgaXMgYWxtb3N0IHR3aWNlIGFzIGxpa2VseSB0byBiZSBhIGNhc2Ugb2YgYW4gb3V0bGllciBUcmF2ZWxUaW1lX1NlYyB2YWx1ZS4KVFRMYXJnZVJ0ZUNobmdfU3ByZWFkCnByb3AudGFibGUoYXMudGFibGUoYXMubWF0cml4KFRUTGFyZ2VSdGVDaG5nX1NwcmVhZCkKICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgMQogICAgICAgICAgKQoKcHJvcC50YWJsZShhcy50YWJsZShhcy5tYXRyaXgoVFRMYXJnZVJ0ZUNobmdfU3ByZWFkKQogICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAyCiAgICAgICAgICApCgojIHJtKFRUTGFyZ2VSdGVDaG5nLCBUVExhcmdlUnRlQ2huZ19TcHJlYWQpCiAgICAgICAgIAoKVmlldyhmaWx0ZXIoVFRMYXJnZVJ0ZUNobmcsCiAgICAgICAgICAgICFpcy5uYShUcmF2ZWxUaW1lX1NlYykgJgogICAgICAgICAgICAgIFJ0ZUNoYW5nZTIgPT0gIlNhbWUiCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsVGltZV9TZWMpLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGhfTmV3SHZycwogICAgICAgICAgICAgICkgJT4lCiAgICAgICBoZWFkKDUwMCkKICAgICkKCgojIGV4YW1wbGVzIHdoZXJlIFRyYXZlbFRpbWVfU2VjIGlzIGxhcmdlIGFuZCBTcGVlZEF2Z19NcGhfTmV3SHZycyBpcyBzbWFsbC4KVmlldyhmaWx0ZXIoVFRMYXJnZVJ0ZUNobmcsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjI1MDI5MCAmIFJvd051bV9PRyA8PSAyMjUwMzEwKSB8ICMgMjI1MDMwMAogICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gODY3NzE3ICYgUm93TnVtX09HIDw9IDg2NzczNykgfCAjIDg2NzcyNwogICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gODY0Mzc5ICYgUm93TnVtX09HIDw9IDg2NDM5OSkgfCAjIDg2NDM4OQogICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gODA4Mzk1ICYgUm93TnVtX09HIDw9IDgwODQxNSkgIyA4MDg0MDUKICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFRyYXZlbFRpbWVfU2VjLgoKSWYgVHJhdmVsVGltZV9TZWMgaXMgYmVsb3cgdGhlIDV0aCBwZXJjZW50aWxlIGZvciB0aGF0IFN0YXJ0U3RvcF9JRCwgb3IgaWYgVHJhdmVsVGltZV9TZWMgaXMgYWJvdmUgdGhlIDk1dGggcGVyY2VudGlsZSBmb3IgdGhhdCBTdGFydFN0b3BfSUQsICBjb25zaWRlciB0aGlzIGFuIG91dGxpZXIuICBJbiB0aGlzIGNhc2UsIHJlcGxhY2UgdGhlIHZhbHVlIHdpdGggdGhlIG1lYW4gZm9yIHRoYXQgU3RhcnRTdG9wX0lEIGFuZCBIb3VyR3JvdXAgKFRUX1NlY19TU0hHX01lYW5fRiksIG9yIGlmIHRoZXJlIGFyZSBub3QgZW5vdWdoIHZhbHVlcyBhdCB0aGUgSG91ckdyb3VwIGxldmVsLCByZXBsYWNlIGl0IHdpdGggdGhlIG1lYW4gZm9yIHRoYXQgU3RhcnRTdG9wX0lELgpgYGB7cn0KCnJtKFRUTGFyZ2VSdGVDaG5nLCBUVExhcmdlUnRlQ2huZ19DbnRzLCBUVExhcmdlUnRlQ2huZ19TcHJlYWQpCgoKTmV3VHJhdlRpbWUgPC0gbXV0YXRlKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19OZXcgPSBpZmVsc2UoIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbFRpbWVfU2VjIDwgVFRfU2VjX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gVFRfU2VjX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfQ250X0YgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU0hHX01lYW5fRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbFRpbWVfU2VjIDwgVFRfU2VjX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gVFRfU2VjX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTSEdfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudF9GID49IDIwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfTWVhbl9GLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsVGltZV9TZWMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsVGltZV9TZWMgPCBUVF9TZWNfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiBUVF9TZWNfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250X0YgPCAyMCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudCA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX01lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxUaW1lX1NlYyA8IFRUX1NlY19TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA+IFRUX1NlY19TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250IDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJ0ZUNoYW5nZTIgPT0gIkNoYW5nZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpKSksCiAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19OZXdfTGFiZWwgPSAKICAgICAgICAgICBmYWN0b3IoaWZlbHNlKCFpcy5uYShUcmF2ZWxUaW1lX1NlYykgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAoVHJhdmVsVGltZV9TZWMgPCBUVF9TZWNfU1NIR19xNSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gVFRfU2VjX1NTSEdfcTk1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NIR19DbnRfRiA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJUVF9TZWNfU1NIR19NZWFuX0YiLAogICAgICAgICAgICAgICAgICBpZmVsc2UoIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIChUcmF2ZWxUaW1lX1NlYyA8IFRUX1NlY19TU0hHX3E1IHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiBUVF9TZWNfU1NIR19xOTUKICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU0hHX0NudF9GIDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250X0YgPj0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVFRfU2VjX1NTX01lYW5fRiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsVGltZV9TZWMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbFRpbWVfU2VjIDwgVFRfU2VjX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA+IFRUX1NlY19TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRUX1NlY19TU19DbnRfRiA8IDIwICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudCA+PSAyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICJUVF9TZWNfU1NfTWVhbiIsCiAgICAgICAgICAgICAgICAgIGlmZWxzZSghaXMubmEoVHJhdmVsVGltZV9TZWMpICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgKFRyYXZlbFRpbWVfU2VjIDwgVFRfU2VjX1NTSEdfcTUgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA+IFRUX1NlY19TU0hHX3E5NQogICAgICAgICAgICAgICAgICAgICAgICAgICApICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgVFRfU2VjX1NTX0NudF9GIDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBUVF9TZWNfU1NfQ250IDwgMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICBSdGVDaGFuZ2UyID09ICJDaGFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVHJhdmVsVGltZV9TZWMiCiAgICAgICAgICAgICAgICAgICAgICAgICkpKSkKICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgVFRfSHJfTmV3ID0gVFRfU2VjX05ldyAvICg2MCAqIDYwKQogICAgICAgICAgICkKCgpkaW0oQWxsRGF5c19OZXdUcmF2ZWxEaXN0KQpkaW0oTmV3VHJhdlRpbWUpCiMgcm0oQWxsRGF5c19OZXdUcmF2ZWxEaXN0KQoKc3VtbWFyeShzZWxlY3QoTmV3VHJhdlRpbWUsCiAgICAgICAgICAgLW1hdGNoZXMoIihxKDJ8NXwoOTUpfCg5OCkpKXxNZWFufE1lZHxDbnQiKQogICAgICAgICAgKQogICApCgpzdHIoc2VsZWN0KE5ld1RyYXZUaW1lLAogICAgICAgICAgIFRyYXZlbFRpbWVfU2VjLAogICAgICAgICAgIFRUX1NlY19OZXcsCiAgICAgICAgICAgVFRfU2VjX05ld19MYWJlbCwKICAgICAgICAgICBUVF9Icl9OZXcKICAgICAgICAgICkKICAgKQoKCnN1bW1hcnkoc2VsZWN0KE5ld1RyYXZUaW1lLAogICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYywKICAgICAgICAgICAgICAgVFRfU2VjX05ldywKICAgICAgICAgICAgICAgVFRfU2VjX05ld19MYWJlbCwKICAgICAgICAgICAgICAgVFRfSHJfTmV3CiAgICAgICAgICAgICAgKQogICAgICAgKQoKYGBgCgoKCmBgYHtyfQoKVmlldyhoZWFkKHNlbGVjdChOZXdUcmF2VGltZSwKICAgICAgICAgICAgICAgICAtbWF0Y2hlcygiKHEoMnw1fCg5NSl8KDk4KSkpfE1lYW58TWVkfENudCIpCiAgICAgICAgICAgICAgICApCiAgICAgICAgICkKICAgICkKClgyIDwtIHNlbGVjdChOZXdUcmF2VGltZSwKICAgICAgICAgICAgIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICAgKSAlPiUgCiAgZmlsdGVyKFJvdXRlID09ICJYMiIpCgpWaWV3KGhlYWQoYXJyYW5nZShYMiwKICAgICAgICAgICAgICAgICAgQnVzX0lELAogICAgICAgICAgICAgICAgICBFdmVudF9UaW1lCiAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgIDUwMAogICAgICAgICApCiAgICApCgpYMl9CeVN0b3AgPC0gZ3JvdXBfYnkoWDIsCiAgICAgICAgICAgICAgICAgICAgICBTdG9wSURfQ2xlYW4KICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgYXJyYW5nZShTdG9wSURfQ2xlYW4sCiAgICAgICAgICBFdmVudF9UaW1lKSAlPiUgCiAgbXV0YXRlKEV2ZW50X1RpbWVfTDEgPSBsYWcoRXZlbnRfVGltZSksCiAgICAgICAgIFRpbWVUb0V2ZW50X1NlYyA9IGFzLm51bWVyaWMoRXZlbnRfVGltZSAtIEV2ZW50X1RpbWVfTDEpLAogICAgICAgICBUaW1lVG9FdmVudF9NaW4gPSBUaW1lVG9FdmVudF9TZWMgLyA2MAogICAgICAgICkKClZpZXcoaGVhZChYMl9CeVN0b3AsIDUwMCkpCgoKIyBDb3VudF9WYWx1ZXMgaXMgbmVlZGVkIHRvIGRpc3BsYXkgdGhlIG1lZGlhbnMgb24gdGhlIGJveCBwbG90cwpDb3VudF9WYWx1ZXMgPC0gZGRwbHkoYXMuZGF0YS5mcmFtZShYMl9CeVN0b3ApLAogICAgICAgICAgICAgICAgICAgICAgLihFdmVudF9UaW1lX0hyR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgc3VtbWFyaXNlLAogICAgICAgICAgICAgICAgICAgICAgVmFsdWVfQ291bnRzID0gbWVkaWFuKFRpbWVUb0V2ZW50X01pbiwgbmEucm0gPSBUUlVFKQogICAgICAgICAgICAgICAgICAgICApCgpEZWx0VGltZV9Cb3hQbG90IDwtIGdncGxvdChzZWxlY3QoYXMuZGF0YS5mcmFtZShYMl9CeVN0b3ApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGltZVRvRXZlbnRfTWluLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXZlbnRfVGltZV9Ickdyb3VwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyhmYWN0b3IoRXZlbnRfVGltZV9Ickdyb3VwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRpbWVUb0V2ZW50X01pbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBmYWN0b3IoRXZlbnRfVGltZV9Ickdyb3VwKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSArIAogIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91cj0icmVkIiwgbm90Y2g9VFJVRSwgbmEucm0gPSBUUlVFKSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBDb3VudF9WYWx1ZXMsCiAgICAgICAgICAgIGFlcyh5ID0gVmFsdWVfQ291bnRzLAogICAgICAgICAgICAgICAgbGFiZWwgPSBmb3JtYXQocm91bmQoVmFsdWVfQ291bnRzLCBkaWdpdHMgPSAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5zbWFsbCA9IDEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICApLAogICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgdmp1c3QgPSAtMC41CiAgICAgICAgICAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUpKSArCiAgY29vcmRfY2FydGVzaWFuKCMgeGxpbSA9IGMoMCwgMTgwKSwKICAgICAgICAgICAgICAgICAgeWxpbSA9IGMoMCwgMTIwKQogICAgICAgICAgICAgICAgICkgKwogIGxhYnModGl0bGUgPSAiVGltZSBCZXR3ZWVuIEJ1c3NlcyAoYXQgdGhlIHNhbWUgc3RvcCwgYnkgSG91ciBHcm91cCkiLAogICAgICAgeCA9ICJIb3VyIEdyb3VwIiwKICAgICAgIHkgPSAiVGltZSBCZXR3ZWVuIEJ1c3NlcyAobWluKSIKICAgICAgKQoKRGVsdFRpbWVfQm94UGxvdAoKCgoKYGBgCgoKSW52ZXN0aWdhdGluZyBUcmF2ZWxUaW1lX1NlYy4KYGBge3J9CgpWaWV3KGZpbHRlcihUVExhcmdlUnRlQ2huZywKICAgICAgICAgICAgIWlzLm5hKFRyYXZlbFRpbWVfU2VjKSAmCiAgICAgICAgICAgICAgUnRlQ2hhbmdlMiA9PSAiU2FtZSIKICAgICAgICAgICApICU+JSAKICAgICAgIGFycmFuZ2UoZGVzYyhUcmF2ZWxUaW1lX1NlYyksCiAgICAgICAgICAgICAgIFNwZWVkQXZnX01waF9OZXdIdnJzCiAgICAgICAgICAgICAgKSAlPiUKICAgICAgIGhlYWQoNTAwKQogICAgKQoKCiMgZXhhbXBsZXMgd2hlcmUgVHJhdmVsVGltZV9TZWMgaXMgc21hbGwgKDEgc2VjKSBhbmQgU3BlZWRBdmdfTXBoX05ld0h2cnMgaXMgbGFyZ2UuClZpZXcoc2VsZWN0KE5ld1RyYXZUaW1lLAogICAgICAgICAgICAjIC1tYXRjaGVzKCIocSgyfDV8KDk1KXwoOTgpKSl8TWVhbnxNZWR8Q250IikKICAgICAgICAgICAgLShURF9NaV9xMjpURF9NaV9TU0hHX0NudF9GKSwKICAgICAgICAgICAgLShUVF9Icl9xMjpUVF9Icl9TU0hHX0NudF9GKQogICAgICAgICAgICkgJT4lIAogICAgICAgZmlsdGVyKChSb3dOdW1fT0cgPj0gMjIxNzM1MyAmIFJvd051bV9PRyA8PSAyMjE3MzczKSB8ICMgMjIxNzM2MwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMDkwMzIxICYgUm93TnVtX09HIDw9IDMwOTAzNDEpIHwgIyAzMDkwMzMxCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDgwNzY0ICYgUm93TnVtX09HIDw9IDgwNzg0KSB8ICMgODA3NzQKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMzM4NDAgJiBSb3dOdW1fT0cgPD0gMzM4NjApICMgMzM4NTAKICAgICAgICAgICApCiAgICApCgoKCgoKCiMgZXhhbXBsZXMgd2hlcmUgVHJhdmVsVGltZV9TZWMgaXMgbGFyZ2UgYW5kIFNwZWVkQXZnX01waF9OZXdIdnJzIGlzIHNtYWxsLgpWaWV3KGZpbHRlcihUVExhcmdlUnRlQ2huZywKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyMjUwMjkwICYgUm93TnVtX09HIDw9IDIyNTAzMTApIHwgIyAyMjUwMzAwCiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4Njc3MTcgJiBSb3dOdW1fT0cgPD0gODY3NzM3KSB8ICMgODY3NzI3CiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4NjQzNzkgJiBSb3dOdW1fT0cgPD0gODY0Mzk5KSB8ICMgODY0Mzg5CiAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA4MDgzOTUgJiBSb3dOdW1fT0cgPD0gODA4NDE1KSAjIDgwODQwNQogICAgICAgICAgICkKICAgICkKYGBgCgoKCgpgYGB7cn0KCiAgICAgICAgIAogICAgICAgICAKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyB1bnVzdWFsbHkgc21hbGwgKHdpdGggVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIGxhcmdlKS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDEwNDIyMjggJiBSb3dOdW1fT0cgPD0gMTA0MjI0OCkgfCAjIDEwNDIyMzgKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNTM4MTYgJiBSb3dOdW1fT0cgPD0gNTM4MzYpIHwgIyA1MzgyNgogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzNjA1NzEgJiBSb3dOdW1fT0cgPD0gMzYwNTkxKSB8ICMgMzYwNTgxCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDUwMjI3MSAmIFJvd051bV9PRyA8PSA1MDIyOTEpICMgNTAyMjgxIChjYW4ndCBleHBsaWFuIHRoZSB3ZWlyZCBUcmF2ZWxUaW1lX1NlYyBjYWxjdWxhdGlvbiBoZXJlIC0gaXQncyBub3QgZXZlbiBhbiBpbnRlZ2VyISkKICAgICAgICAgICApCiAgICApCgojIHN0aWxsIHRyeWluZyB0byBleHBsYWluIDUwMjI4MS4uLm9uIHRoZSBkYXkgb2YgdGhpcyB3ZWlyZG5lc3MsIHRoZSBidXMgd2FzIG9ubHkgaW4gY2lyY3VsYXRpb24gZm9yIDQtNSBzdG9wcyAofjIwIG1pbnV0ZXMpIG9uIHRoYXQgZGF5IChPY3QgNikKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICBCdXNfSUQgPT0gMjcxMQogICAgICAgICAgICkKICAgICkKCgojIGV4cGxvcmluZyBsYXJnZSB2YWx1ZXMgZm9yIFRyYXZlbFRpbWVfU2VjClZpZXcoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPT0gMzAwCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsVGltZV9TZWMpLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyCiAgICAgICAgICAgICAgKQogICAgKQoKIyBleGFtcGxlcyB3aGVyZSBUcmF2ZWxUaW1lX1NlYyBpcyB1bnVzdWFsbHkgbGFyZ2UgKHdpdGggVHJhdmVsRGlzdGFuY2VfTWkgdmFsdWVzIHRoYXQgYXJlIHNtYWxsLCBzbyBTcGVlZEF2Z19NcGggdmFsdWVzIGFyZSB2ZXJ5IHNtYWxsKS4KVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDI2Mjc0NTkgJiBSb3dOdW1fT0cgPD0gMjYyNzQ3OSkgfCAjIDI2Mjc0NjkKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjE5MzM0NCAmIFJvd051bV9PRyA8PSAyMTkzMzY0KSB8ICMgMjE5MzM1NAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjQ0MTIzICYgUm93TnVtX09HIDw9IDE2NDQxNDMpIHwgIyAxNjQ0MTMzCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDg2OTYwMCAmIFJvd051bV9PRyA8PSA4Njk2MjApICMgODY5NjEwCiAgICAgICAgICAgKQogICAgKQoKYGBgCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIKClZpZXcoU3BlZWRfUGN0aWxlcyk6IDkwJSBvZiBTcGVlZEF2Z19NcGgyIGFyZSBiZXR3ZWVuIH4zbXBoIGFuZCB+NjZtcGguCmBgYHtyfQoKU3BlZWRfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShBbGxEYXlzX05ld1RyYXZlbERpc3QkU3BlZWRBdmdfTXBoMikgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShBbGxEYXlzX05ld1RyYXZlbERpc3QkU3BlZWRBdmdfTXBoMiwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKEFsbERheXNfTmV3VHJhdmVsRGlzdCRTcGVlZEF2Z19NcGgyKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld1RyYXZlbERpc3QkU3BlZWRBdmdfTXBoMiksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgpjb2xuYW1lcyhTcGVlZF9OdGlsZSlbMV0gPC0gIlNwZWVkQXZnX01waDIiCnN0cihTcGVlZF9OdGlsZSkKClNwZWVkX050aWxlX1Jvd3MgPC0gbnJvdyhTcGVlZF9OdGlsZSkKClZpZXcodGFpbChTcGVlZF9OdGlsZSwgNTAwKSkKCgpTcGVlZF9QY3RpbGVzIDwtIGdyb3VwX2J5KFNwZWVkX050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblNwZWVkQXRQY3RpbGUgPSBtaW4oU3BlZWRBdmdfTXBoMiksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBTcGVlZF9OdGlsZV9Sb3dzCiAgKSAlPiUgCiAgbXV0YXRlKEN1bVN1bVBBdFAgPSBjdW1zdW0oUGN0c0F0UGN0aWxlKQogICAgICAgICkKClZpZXcoU3BlZWRfUGN0aWxlcykKCmBgYAoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKRXhwbG9yaW5nIHRoZSByZW1vdmFsIG9mIG91dGxpZXIgVHJhdmVsVGltZV9TZWMgYW5kIFRyYXZlbERpc3RhbmNlX01pLgpgYGB7cn0KCnN1bW1hcnkoc2VsZWN0KEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgU3BlZWRBdmdfTXBoLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyCiAgICAgICAgICAgICAgKQogICAgICAgKQoKc3VtbWFyeShzZWxlY3QoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pID4gMC4wMDAxODkzOTM5ICYgIyBsb3dlc3Qgbm9uLXplcm8gcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxEaXN0YW5jZV9NaSA8IDEuMDgxMjUwMDAwMCAmICMgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gMTAuMDUwMDAwICYgIyAybmQgcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYyA8IDI5My4wMDAwMDAgIyA5OHRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgU3BlZWRBdmdfTXBoLAogICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyCiAgICAgICAgICAgICAgKQogICAgICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKSGlzdG9ncmFtIG9mIFNwZWVkQXZnX01waDIuCmBgYHtyfQoKU3BlZWRfSGlzdERlbiA8LSBnZ3Bsb3QoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShTcGVlZEF2Z19NcGgyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IFNwZWVkQXZnX01waDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gLi5kZW5zaXR5Li4KICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNSwgZmlsbCA9ICJsaWdodGJsdWUiLCBjb2xvdXIgPSAiZ3JleTYwIiwgc2l6ZSA9IDAuMikgKwogIGdlb21fbGluZShzdGF0ID0gImRlbnNpdHkiLCBjb2xvdXIgPSAicmVkIikgKwogIHN0YXRfYmluKGJpbndpZHRoID0gNSwKICAgICAgICAgICBnZW9tID0gInRleHQiLAogICAgICAgICAgIHNpemUgPSAyLjUsCiAgICAgICAgICAgdmp1c3QgPSAxLjUsCiAgICAgICAgICAgYWVzKGxhYmVsID0gZm9ybWF0KC4uY291bnQuLiwgYmlnLm1hcmsgPSAiLCIpCiAgICAgICAgICAgICAgKSwKICAgICAgICAgICkgKwogICMgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGZvcm1hdCguLmNvdW50Li4sIGJpZy5tYXJrID0gIiwiKQogICMgICAgICAgICAgICAgICksCiAgIyAgICAgICAgICAgc2l6ZSA9IDMsCiAgIyAgICAgICAgICAgbnVkZ2VfeSA9ICguLmNvdW50Li4gKiAwLjEpCiAgIyAgICAgICAgICApICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgNzApLCB5bGltID0gYygwLCAwLjA0KQogICAgICAgICAgICAgICAgICkgKwogICMgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIlZhcmlhdGlvbiBpbiBUcmF2ZWwgU3BlZWQiLAogICAgICAgeCA9ICJBdmVyYWdlIFNwZWVkIChtcGgpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIKICAgICAgKQoKU3BlZWRfSGlzdERlbgoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKSGlzdG9ncmFtIG9mIFNwZWVkQXZnX01waDIgYWZ0ZXIgcmVtb3Zpbmcgb3V0bGllciBUcmF2ZWxUaW1lX1NlYyBhbmQgVHJhdmVsRGlzdGFuY2VfTWkuCmBgYHtyfQoKVmlldyhUcmF2RGlzdE1pTmV3X1BjdGlsZXMpClZpZXcoVHJhdlRpbWVIcl9QY3RpbGVzKQoKU3BlZWROb091dGxpZXJfSGlzdERlbiA8LSBnZ3Bsb3QoZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFpcy5uYShTcGVlZEF2Z19NcGgyKSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IDAuMDc3ODQxMDA1ICYgIyA1dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbERpc3RhbmNlX01pX05ldyA8IDEuMDgxMjUwMDAwMCAmICMgOTl0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gMTIuMTAwMDAwICMgNHRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUcmF2ZWxUaW1lX1NlYyA8IDI5My4wMDAwMDAgIyA5OHRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBTcGVlZEF2Z19NcGgyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IC4uZGVuc2l0eS4uCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIGZpbGwgPSAibGlnaHRibHVlIiwgY29sb3VyID0gImdyZXk2MCIsIHNpemUgPSAwLjIpICsKICBnZW9tX2xpbmUoc3RhdCA9ICJkZW5zaXR5IiwgY29sb3VyID0gInJlZCIpICsKICBzdGF0X2JpbihiaW53aWR0aCA9IDUsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMi41LAogICAgICAgICAgIHZqdXN0ID0gMS41LAogICAgICAgICAgIGFlcyhsYWJlbCA9IGZvcm1hdCguLmNvdW50Li4sIGJpZy5tYXJrID0gIiwiKQogICAgICAgICAgICAgICksCiAgICAgICAgICApICsKICAjIGdlb21fdGV4dChhZXMobGFiZWwgPSBmb3JtYXQoLi5jb3VudC4uLCBiaWcubWFyayA9ICIsIikKICAjICAgICAgICAgICAgICApLAogICMgICAgICAgICAgIHNpemUgPSAzLAogICMgICAgICAgICAgIG51ZGdlX3kgPSAoLi5jb3VudC4uICogMC4xKQogICMgICAgICAgICAgKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDcwKSwgeWxpbSA9IGMoMCwgMC4wNCkKICAgICAgICAgICAgICAgICApICsKICAjICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJWYXJpYXRpb24gaW4gVHJhdmVsIFNwZWVkIiwKICAgICAgIHN1YnRpdGxlID0gIihyZW1vdmVkIGxvdyBvdXRsaWVycyBvZiBUcmF2ZWwgRGlzdGFuY2UgYW5kIFRyYXZlbCBUaW1lKSIsCiAgICAgICB4ID0gIkF2ZXJhZ2UgU3BlZWQgKG1waCkiLAogICAgICAgeSA9ICJEZW5zaXR5IgogICAgICApCgpTcGVlZE5vT3V0bGllcl9IaXN0RGVuCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwZWVkQXZnX01waDIuCgpOZXcgZGF0YXNldCAoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUpIHdoZW4gcmVtb3Zpbmcgb3V0bGllciBsb3cgdmFsdWVzIG9mIFRyYXZlbERpc3RhbmNlX01pX05ldyBhbmQgVHJhdmVsVGltZV9TZWMuCmBgYHtyfQoKVmlldyhUcmF2RGlzdE1pTmV3X1BjdGlsZXMpClZpZXcoVHJhdlRpbWVIcl9QY3RpbGVzKQoKTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUgPC0gZmlsdGVyKEFsbERheXNfTmV3VHJhdmVsRGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbERpc3RhbmNlX01pX05ldyA+IC4wNzc4NDEwMDUgJiAjIDV0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgVHJhdmVsRGlzdGFuY2VfTWlfTmV3IDwgMS4wODEyNTAwMDAwICYgIyA5OXRoIHBlcmNlbnRpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMgPiAxMi4xMDAwMDAgIyA0dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFRyYXZlbFRpbWVfU2VjIDwgMjkzLjAwMDAwMCAjIDk4dGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpucm93KEFsbERheXNfTmV3VHJhdmVsRGlzdCkgLSBucm93KE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKQoKc3RyKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKQpzdW1tYXJ5KE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcHBlZEF2Z19NcGgyLgoKVmlldyhTcGVlZF9Ob091dF9QY3RpbGVzKTogIEFwcm94aW1hdGVseSA5MCUgb2YgU3BlZWRBdmdfTXBoMiB2YWx1ZXMgYXJlIGJldHdlZW4gfjRtcGggYW5kIH41Nm1waC4KYGBge3J9CgpTcGVlZF9Ob091dF9OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lJFNwZWVkQXZnX01waDIpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoTm9PdXRsaWVyc19UcmF2ZWxEaXN0TlRpbWUkU3BlZWRBdmdfTXBoMiwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lJFNwZWVkQXZnX01waDIpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lJFNwZWVkQXZnX01waDIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoU3BlZWRfTm9PdXRfTnRpbGUpWzFdIDwtICJTcGVlZEF2Z19NcGgyIgpzdHIoU3BlZWRfTm9PdXRfTnRpbGUpCgpTcGVlZF9Ob091dF9OdGlsZV9Sb3dzIDwtIG5yb3coU3BlZWRfTm9PdXRfTnRpbGUpCgpWaWV3KHRhaWwoU3BlZWRfTm9PdXRfTnRpbGUsIDUwMCkpCgoKU3BlZWRfTm9PdXRfUGN0aWxlcyA8LSBncm91cF9ieShTcGVlZF9Ob091dF9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5TcGVlZEF0UGN0aWxlID0gbWluKFNwZWVkQXZnX01waDIpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gU3BlZWRfTm9PdXRfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSkKICAgICAgICApCgpWaWV3KFNwZWVkX05vT3V0X1BjdGlsZXMpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIFNwcGVkQXZnX01waDIuCgpFeGxvcmluZyBvZGQvaW1wb3NzaWJsZSB2YWx1ZXMuCmBgYHtyfQoKIyBFeHBsb3Jpbmcgd2hlbiBTcGVlZEF2Z19NcGgyIGlzIE5BICAtLSAgZG9lcyBub3Qgb2NjdXIgYXQgYWxsCm5yb3coZmlsdGVyKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lLAogICAgICAgICAgICBpcy5uYShTcGVlZEF2Z19NcGgyKQogICAgICAgICAgICkKICAgICkKCgojIEV4cGxvcmluZyB3aGVuIFNwZWVkQXZnX01waDIgaXMgemVybyAgLS0gIGRvZXMgbm90IG9jY3VyIGF0IGFsbApucm93KGZpbHRlcihOb091dGxpZXJzX1RyYXZlbERpc3ROVGltZSwKICAgICAgICAgICAgU3BlZWRBdmdfTXBoMiA9PSAwCiAgICAgICAgICAgKQogICAgKQoKCiMgZXhhbXBsZXMgd2hlcmUgU3BlZWRBdmdfTXBoMiA8IDMuMjg0ODc3MApWaWV3KGZpbHRlcihBbGxEYXlzX05ld1RyYXZlbERpc3QsCiAgICAgICAgICAgIFNwZWVkQXZnX01waDIgPiAwICYKICAgICAgICAgICAgICBTcGVlZEF2Z19NcGgyIDwgMy4yODQ4NzcwCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKFNwZWVkQXZnX01waDIpCiAgICApCgojIGV4YW1wbGVzIHdoZXJlIFNwZWVkQXZnX01waDIgPCAzLjI4NDg3NzAKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdUcmF2ZWxEaXN0LAogICAgICAgICAgICAoUm93TnVtX09HID49IDQ4NTMzOCAmIFJvd051bV9PRyA8PSA0ODUzNTgpIHwgIyA0ODUzNDggIC0tICBFeHRyZW1lIHRyYXZlbCB0aW1lLCBSb3V0ZSBDaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMzQ2OTUyICYgUm93TnVtX09HIDw9IDM0Njk3MikgfCAjIDM0Njk2MiAgLS0gRXh0cmVtZSB0cmF2ZWwgdGltZSwgUm91dGUgQ2hhbmdlIAogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA3MDQ5NCAmIFJvd051bV9PRyA8PSA3MDUxNCkgfCAjIDcwNTA0ICAtLSAgRXh0cmVtZSB0cmF2ZWwgdGltZSwgUm91dGUgQ2hhbmdlCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDIwNTE4NDYgJiBSb3dOdW1fT0cgPD0gMjA1MTg2NikgIyAyMDUxODU2ICAtLSAgRXh0cmVtZSB0cmF2ZWwgdGltZSwgUm91dGUgQ2hhbmdlCiAgICAgICAgICAgKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBTcGVlZEF2Z19NcGgyLgoKTGltaXQgdGhlIGRhdGFzZXQgYmFzZWQgb24gU3BlZWRBdmdfTXBoMi4KYGBge3J9CgpOb091dGxpZXJzU3BlZWQgPC0gZmlsdGVyKE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIGJldHdlZW4oU3BlZWRBdmdfTXBoMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDQuMDY5MzAwLCAjIDV0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA1Ni4wNTY1MSAjOTV0aCBwZXJjZW50aWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApCgpucm93KE5vT3V0bGllcnNfVHJhdmVsRGlzdE5UaW1lKSAtIG5yb3coTm9PdXRsaWVyc1NwZWVkKQoKc3VtbWFyeShOb091dGxpZXJzU3BlZWQpCgpgYGAKCgpUcmF2ZWxUaW1lIG5vdyBsb29rcyBsaWtlIGl0IGhhcyBzb21lIG9kZCB2YWx1ZXMgb24gdGhlIGhpZ2ggZW5kLiAgU28gbGV0J3MgbG9vayBhdCB0aG9zZS4KClZpZXcoVHJhdlRpbWVfTm9PdXRfUGN0aWxlcyk6ICBWaXJ0dWFsbHkgYWxsIHRyaXBzIHNob3VsZCB0YWtlIGxlc3MgdGhhbiA1IG1pbnV0ZXMuIChUaGUgOTl0aCBwZXJjZW50aWxlIG9mIG9mIFRyYXZlbFRpbWUgaXMgYXBwcm94aW1hdGVseSA4IG1pbnV0ZXMuKQpgYGB7cn0KClRyYXZUaW1lX05vT3V0X050aWxlIDwtIGFzLmRhdGEuZnJhbWUoTm9PdXRsaWVyc1NwZWVkJFRyYXZlbFRpbWVfSHIpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoTm9PdXRsaWVyc1NwZWVkJFRyYXZlbFRpbWVfSHIsIDEwMCksCiAgICAgICAgIE1pblIgPSBtaW5fcmFuayhOb091dGxpZXJzU3BlZWQkVHJhdmVsVGltZV9IciksCiAgICAgICAgIFBjdFIgPSBwZXJjZW50X3JhbmsoTm9PdXRsaWVyc1NwZWVkJFRyYXZlbFRpbWVfSHIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApCgpjb2xuYW1lcyhUcmF2VGltZV9Ob091dF9OdGlsZSlbMV0gPC0gIlRyYXZlbFRpbWVfSHIiCnN0cihUcmF2VGltZV9Ob091dF9OdGlsZSkKClRyYXZUaW1lX05vT3V0X050aWxlX1Jvd3MgPC0gbnJvdyhUcmF2VGltZV9Ob091dF9OdGlsZSkKClZpZXcodGFpbChUcmF2VGltZV9Ob091dF9OdGlsZSwgNTAwKSkKCgpUcmF2VGltZV9Ob091dF9QY3RpbGVzIDwtIGdyb3VwX2J5KFRyYXZUaW1lX05vT3V0X050aWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHN1bW1hcmlzZSgKICAgIE1pblRyYXZUaW1lSHJBdFBjdGlsZSA9IG1pbihUcmF2ZWxUaW1lX0hyKSwKICAgIENudHNBdFBjdGlsZSA9IG4oKSwKICAgIFBjdHNBdFBjdGlsZSA9IENudHNBdFBjdGlsZSAvIFRyYXZUaW1lX05vT3V0X050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpLAogICAgICAgICBNaW5UcmF2VGltZVNlY0F0UGN0aWxlID0gTWluVHJhdlRpbWVIckF0UGN0aWxlICogKDYwICogNjApCiAgICAgICAgKQoKVmlldyhUcmF2VGltZV9Ob091dF9QY3RpbGVzKQoKYGBgCgoKSW52ZXN0aWdhdGluZyBvZGQgVHJhdmVsVGltZV9TZWMgdmFsdWVzLgoKVHJpcHMgbG9uZ2VyIHRoYW4gfjggbWludXRlcy4KYGBge3J9CgpWaWV3KGZpbHRlcihOb091dGxpZXJzU3BlZWQsCiAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjID4gNDkxICMgbWluIGF0IHRoZSAxMDB0aCBwZXJjZW50aWxlCiAgICAgICAgICAgKSAlPiUgCiAgICAgICBhcnJhbmdlKGRlc2MoVHJhdmVsVGltZV9TZWMpCiAgICAgICAgICAgICAgKQogICAgKQoKIyBleGFtcGxlcyBvZiBUcmF2ZWxUaW1lX1NlYyB2YWx1ZXMgdGhhdCBhcmUgbGFyZ2VzdC4KVmlldyhmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAoUm93TnVtX09HID49IDIwNzE3NTkgJiBSb3dOdW1fT0cgPD0gMjA3MTc3OSkgfCAjIDIwNzE3NjkgIC0tICByZXN1bHRzIGZyb20gYSByb3V0ZSBjaGFuZ2UsIGFuZCBhIDNocisgd2FpdCBiZWZvcmUgdGhlIG5ldyByb3V0ZSBzdGFydHMKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTQ3MzY4NiAmIFJvd051bV9PRyA8PSAxNDczNzA2KSB8ICMgMTQ3MzY5NiAgLS0gIHJlc3VsdHMgZnJvbSBhIHJvdXRlIGNoYW5nZSwgYW5kIGEgM2hyIHdhaXQgYmVmb3JlIHRoZSBuZXcgcm91dGUgc3RhcnRzCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDEyMjI4MjIgJiBSb3dOdW1fT0cgPD0gMTIyMjg0MikgfCAjIDEyMjI4MzIgIC0tICByZXN1bHRzIGZyb20gYSByb3V0ZSBjaGFuZ2UsIGFuZCBhIDNociB3YWl0IGJlZm9yZSB0aGUgbmV3IHJvdXRlIHN0YXJ0cwogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMDQ2MDg5ICYgUm93TnVtX09HIDw9IDMwNDYxMDkpICMgMzA0NjA5OSAgLS0gIHJlc3VsdHMgZnJvbSBhIHJvdXRlIGNoYW5nZSwgYW5kIGEgM2hyIHdhaXQgYmVmb3JlIHRoZSBuZXcgcm91dGUgc3RhcnRzCiAgICAgICAgICAgKQogICAgKQoKCiMgZXhhbXBsZXMgb2YgVHJhdmVsVGltZV9TZWMgdmFsdWVzIHRoYXQgYXJlIHRoZSBzbWFsbGVzdCBvZiB0aGUgbGFyZ2UuClZpZXcoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgKFJvd051bV9PRyA+PSAzMDQ0Njg5ICYgUm93TnVtX09HIDw9IDMwNDQ3MDkpIHwgIyAzMDQ0Njk5ICAtLSAgcmVzdWx0cyBmcm9tIGEgcm91dGUgY2hhbmdlCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDMwMjIzNTggJiBSb3dOdW1fT0cgPD0gMzAyMjM3OCkgfCAjIDMwMjIzNjggIC0tICByZXN1bHRzIGZyb20gYSByb3V0ZSBjaGFuZ2UKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjk5MzAxNiAmIFJvd051bV9PRyA8PSAyOTkzMDM2KSB8ICMgMjk5MzAyNiAgLS0gIHJlc3VsdHMgZnJvbSBhIHByZXZpb3VzIHJvdXRlIGNoYW5nZSAoY2hhbmdlIG9jY3VycmVkIGluIGRlbGV0ZWQgcm93KQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAyNjgzNzAzICYgUm93TnVtX09HIDw9IDI2ODM3MjMpICMgMjY4MzcxMyAgLS0gIHJlc3VsdHMgZnJvbSBhIHByZXZpb3VzIHJvdXRlIGNoYW5nZSAoY2hhbmdlIG9jY3VycmVkIGluIGRlbGV0ZWQgcm93KQogICAgICAgICAgICkKICAgICkKCmBgYAoKCkxldCdzIGxvb2sgYXQgdGhlIFRyYXZlbFRpbWVfU2VjIHZhbHVlcyBhbmQgcm91dGUgY2hhbmdlcyAoRGlyQ2hhbmdlMikuCgpUaGUgOTl0aCBwZXJjZW50aWxlIG9mIFRyYXZlbFRpbWVfU2VjIGZvciBib3RoLCBhbGwgdHJpcHMsIGFuZCBqdXN0IHRob3NlIHRyaXBzIE5PVCBpbnZvbHZpbmcgcm91dGUgY2hhbmdlcyAoRGlyQ2hhbmdlMiA9ICJTYW1lIiksIGlzIGFwcHJveGltYXRlbHkgNW1pbiAoMzAwIHNlYykuCgpOb3RhIEJlbmU6ICBUaGUgcGVyY2VudGlsZSBjYWxjdWxhdGlvbiBoZXJlIGlzIGRlZmluZWQgc2xpZ2h0bHkgZGlmZmVyZW50IHRoYW4gaW4gbW9zdCBvZiB0aGUgYWJvdmUgYW5hbHlzZXMgKHdoaWNoIGdldCB0aGUgbG93ZXN0IHZhbHVlIGluIHRoZSBiaW4gY3JlYXRlZCBieSAxMDAgbnRpbGVzKS4KYGBge3J9CgpzdW1tYXJ5KHNlbGVjdChOb091dGxpZXJzU3BlZWQsCiAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgKQogICAgICAgKQoKc3VtbWFyeShzZWxlY3QoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgIERpckNoYW5nZTIgPT0gIlNhbWUiCiAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgKQogICAgICAgKQoKc3VtbWFyeShzZWxlY3QoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgIERpckNoYW5nZTIgPT0gIkNoYW5nZSIKICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgVHJhdmVsVGltZV9TZWMKICAgICAgICAgICAgICApCiAgICAgICApCgoKVHJhdlRpbWVTZWNfUXRpbGVzX2RmIDwtIGRhdGEuZnJhbWUoUGN0VmFsdWUgPSBzZXEoMCwgMTAwLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQWxsID0gc2VxKDEsIDEwMSwgMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNhbWUgPSBzZXEoMSwgMTAxLCAxKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2hhbmdlID0gc2VxKDEsIDEwMSwgMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpUcmF2VGltZVNlY19RdGlsZXNfZGZbICwgMl0gPC0gcXVhbnRpbGUoc2VsZWN0KE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2JzID0gc2VxKDAsIDEsIDAuMDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKClRyYXZUaW1lU2VjX1F0aWxlc19kZlsgLCAzXSA8LSBxdWFudGlsZShzZWxlY3QoZmlsdGVyKE5vT3V0bGllcnNTcGVlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlyQ2hhbmdlMiA9PSAiU2FtZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBzZXEoMCwgMSwgMC4wMSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKVHJhdlRpbWVTZWNfUXRpbGVzX2RmWyAsIDRdIDwtIHF1YW50aWxlKHNlbGVjdChmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaXJDaGFuZ2UyID09ICJDaGFuZ2UiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUcmF2ZWxUaW1lX1NlYwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2JzID0gc2VxKDAsIDEsIDAuMDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKClZpZXcoVHJhdlRpbWVTZWNfUXRpbGVzX2RmKQoKYGBgCgoKTGltaXQgdGhlIGRhdGFzZXQgbm93IGJhc2VkIG9uIFRyYXZlbFRpbWVfU2VjLgpgYGB7cn0KClVwcGVyTGltaXRUcmF2VGltZSA8LSBmaWx0ZXIoTm9PdXRsaWVyc1NwZWVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRyYXZlbFRpbWVfU2VjIDw9IDQ5MSAjIG1pbiBhdCB0aGUgMTAwdGggcGVyY2VudGlsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCm5yb3coTm9PdXRsaWVyc1NwZWVkKSAtIG5yb3coVXBwZXJMaW1pdFRyYXZUaW1lKQoKc3RyKFVwcGVyTGltaXRUcmF2VGltZSkKCnN1bW1hcnkoVXBwZXJMaW1pdFRyYXZUaW1lKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEd2VsbF9UaW1lMiAoaG93IGxvbmcgdGhlIGJ1cyBpcyBhdCBhIHN0b3ApLgoKRGlmZmVyZW5jZXMgYmV0d2VlbiBEd2VsbF9UaW1lIChieSBXTUFUQSkgYW5kIER3ZWxsX1RpbWUyIChieSBtZSkgYXBwZWFyIHRvIGJlIGR1ZSB0byBzd2l0Y2hlcyBpbiBSb3V0ZUFsdC4gV01BVEEgY2FsY3VsYXRlcyBEd2VsbF9UaW1lIGJ5IGFuIHVua25vd24gcHJvY2Vzcy4gVGhlIFdNQVRBIGNhbGN1bGF0aW9uIGlzIGVxdWFsIHRvIG15IGNhbGN1bGF0aW9uLCBleGNlcHQgZm9yIHRoZSByZWNvcmRzIGltbWVkYWl0ZWx5IGJlZm9yZSBhbmQgYWZ0ZXIgYSBSb3V0ZUFsdCBzd2l0Y2ggKERpckNoYW5nZTIpLgpgYGB7cn0KClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIER3ZWxsX1RpbWUgIT0gRHdlbGxfVGltZTIKICAgICAgICAgICApCiAgICApCgoKIyBFeGFtcGxlcyB3aGVyZSB0aGUgRHdlbGxfVGltZSBhbmQgRHdlbGxfVGltZTIgYXJlIGRpZmZlcmVudApWaWV3KGZpbHRlcihBbGxEYXlzX05ld09yZGVyLAogICAgICAgICAgICAoIChSb3dOdW1fT0cgPj0gNjUgJiBSb3dOdW1fT0cgPD0gODUpIHwgIyA3NQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSAxNjIgJiBSb3dOdW1fT0cgPD0gMTkyKSB8ICMgMTcyCiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDQzMTk1MiAmIFJvd051bV9PRyA8PSA0MzE5NzIpIHwgIyA0MzE5NjIKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gNDM0NTk1ICYgUm93TnVtX09HIDw9IDQzNDYxNSkgIyA0MzQ2MDUgIC0tICB0aGlzIHJlY29yZCBpcyBOT1QgYSByb3V0ZSBzd2l0Y2gsIGJ1dCBkb2VzIGhhcyBhIFNlcXVlbmNlIHN3aXRjaCAoTWU6IHNob3VsZCB0aGVyZSByZWFsbHkgYmUgYSByb3V0ZSBzd2l0Y2ggaGVyZT8pCiAgICAgICAgICAgICkKICAgICAgICAgICApCiAgICApCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIER3ZWxsX1RpbWUyIChob3cgbG9uZyB0aGUgYnVzIGlzIGF0IGEgc3RvcCkuCgpGaXJzdCwgY3JlYXRlIHNvbWUgInJhbmsiIHN0YXRzLgpWaWV3KERUMl9QY3RpbGVzKTogOTUlIG9mIER3ZWxsX1RpbWUycyBhcmUgPD0gMjMgc2Vjb25kcy4uLmJ1dCBzb21lIHdlaXJkIChlLmcuLCBuZWFybHkgMiBob3VyIER3ZWxsX1RpbWUycyBleGlzdCkuCmBgYHtyfQoKRHdlbGxUaW1lMl9OdGlsZSA8LSBhcy5kYXRhLmZyYW1lKEFsbERheXNfTmV3T3JkZXIkRHdlbGxfVGltZTIpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoQWxsRGF5c19OZXdPcmRlciREd2VsbF9UaW1lMiwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKEFsbERheXNfTmV3T3JkZXIkRHdlbGxfVGltZTIpLAogICAgICAgICBQY3RSID0gcGVyY2VudF9yYW5rKEFsbERheXNfTmV3T3JkZXIkRHdlbGxfVGltZTIpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoRHdlbGxUaW1lMl9OdGlsZSlbMV0gPC0gIkR3ZWxsX1RpbWUyIgpzdHIoRHdlbGxUaW1lMl9OdGlsZSkKCkR3ZWxsVGltZTJfTnRpbGVfUm93cyA8LSBucm93KER3ZWxsVGltZTJfTnRpbGUpCgpWaWV3KHRhaWwoRHdlbGxUaW1lMl9OdGlsZSwgNTAwKSkKCgpEd2VsbFRpbWUyX1BjdGlsZXMgPC0gZ3JvdXBfYnkoRHdlbGxUaW1lMl9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdFJfUm91bmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgTWluRHdlbGxBdFBjdGlsZSA9IG1pbihEd2VsbF9UaW1lMiksCiAgICBDbnRzQXRQY3RpbGUgPSBuKCksCiAgICBQY3RzQXRQY3RpbGUgPSBDbnRzQXRQY3RpbGUgLyBEd2VsbFRpbWUyX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpCiAgICAgICAgKQoKVmlldyhEd2VsbFRpbWUyX1BjdGlsZXMpCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIER3ZWxsX1RpbWUyIChob3cgbG9uZyB0aGUgYnVzIGlzIGF0IGEgc3RvcCkuCgpIaXN0b2dyYW0gb2YgRHdlbGxfVGltZTIuCmBgYHtyfQoKRHdlbGxUaW1lMl9IaXN0RGVuIDwtIGdncGxvdChBbGxEYXlzX05ld09yZGVyLCBhZXMoeCA9IER3ZWxsX1RpbWUyLCB5ID0gLi5kZW5zaXR5Li4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAxLCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAiZGVuc2l0eSIsIGNvbG91ciA9ICJyZWQiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDEsIDI1KSwgeWxpbSA9IGMoMCwgMC4wNSkKICAgICAgICAgICAgICAgICApICsKICB4bGFiKCJUaW1lIGEgQnVzIFN0YXlzIGF0IGEgU3RvcCAoc2VjKSIpICsgCiAgeWxhYigiRGVuc2l0eSIpICsgCiAgIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyAKICBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiVmFyaWF0aW9uIGluIEhvdyBMb25nIGEgQnVzIFN0YXlzIGF0IGEgU3RvcCIKICAgICAgICAgICAgICAgICAgICAgICAgICAjICxhdG9wKGl0YWxpYygieHh4eHgiKSwiIikKICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICkKCkR3ZWxsVGltZTJfSGlzdERlbgoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEd2VsbF9UaW1lMiAoaG93IGxvbmcgdGhlIGJ1cyBpcyBhdCBhIHN0b3ApLgoKTG9va2luZyBhdCBzb21lIHdlaXJkbHkgbG9uZyBEd2VsbF9UaW1lMiB2YWx1ZXMuCmBgYHtyfQoKVmlldyhhcnJhbmdlKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICBkZXNjKER3ZWxsX1RpbWUyKQogICAgICAgICAgICApCiAgICApCgoKIyBleGFtcGxlcyBvZiBleHRyZW1lbHkgbGFyZ2UgRHdlbGxfVGltZTJzClZpZXcoZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMjkyNjY5ICYgUm93TnVtX09HIDw9IDI5MjY4OSkgfCAjIDI5MjY3OQogICAgICAgICAgICAgICAgKFJvd051bV9PRyA+PSA1MzEwNTcgJiBSb3dOdW1fT0cgPD0gNTMxMDc3KSB8ICMgNTMxMDY3CiAgICAgICAgICAgICAgICAoUm93TnVtX09HID49IDEzODg2MjcgJiBSb3dOdW1fT0cgPD0gMTM4ODY0NykgfCAjIDEzODg2MzcKICAgICAgICAgICAgICAgIChSb3dOdW1fT0cgPj0gMTY0NTcxMSAmIFJvd051bV9PRyA8PSAxNjQ1NzMxKSAjIDE2NDU3MjEKICAgICAgICAgICApCiAgICApCgoKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgRHdlbGxfVGltZTIgPT0gMAogICAgICAgICAgICkKICAgICkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRGVsdGFfVGltZSAoaG93IGVhcmx5IG9yIGxhdGUgdGhlIGJ1cyBpcykuCgpWaWV3KERUMl9QY3RpbGVzKTogOTQlIG9mIERlbHRhX1RpbWUgdmFsdWVzIGFyZSBiZXR3ZWVuIC0yMzYgc2Vjb25kcyBhbmQgMSwyNTkgc2Vjb25kcy4gUm91Z2hseSA2NiUgb2YgcmVjb3JkcyBhcmUgd2l0aGluIDUgbWluIGxhdGUgYW5kIDUgbWluIGVhcmx5Li4uYnV0IHNvbWUgd2VpcmQgKGUuZy4sIGFsbW9zdCA1MCBtaW51dGUgbGF0ZSBvciA0MCBtaW51dGUgZWFybHkpIERlbHRhX1RpbWVzIGV4aXN0LgoKTm90ZSB0aGF0IERlbHRhX1RpbWUgaXMgdGhlIGRpZmZlcmVuY2UgZnJvbSB0aGUgc2NoZWR1bGVkIGJ1cyBhcnJpdmFsLiBTbyBpZiB0d28gYnVzZXMgYXJlIHNjaGVkdWxlZCB0byBhcnJpdmUgYXQgYSBkZXN0aW5hdGlvbiBhdCAxMDowMHBtIGFuZCAxMDoyMHBtLCBhbmQgaWYgdGhlIDEwOjIwcG0gYnVzIGhhcyBhIERlbHRhX1RpbWUgb2YgNSBtaW51dGVzLCB0aGVyZSBhcmUgMjUgbWludXRlcyBiZXR3ZWVuIGJ1cyBhcnJpdmFscyBhdCB0aGUgc3RvcC4KCkFsc28gbm90ZSB0aGF0IGJhc2VkIG9uIGEgY29tbWVudCBhdCBodHRwczovL3BsYW5pdG1ldHJvLmNvbS8yMDE2LzExLzE2L2RhdGEtZG93bmxvYWQtbWV0cm9idXMtdmVoaWNsZS1sb2NhdGlvbi1kYXRhLywgdGhlIERlbHRhX1RpbWUgdmFsdWVzIGRvbid0IGFwcGVhciB0byBjb2luY2lkZSB3aXRoIHB1Ymxpc2hlZCBidXMgc2NoZWR1bGVzIChlLmcuLCB0aGUgWDIgZGVwYXJ0aW5nIGV2ZXJ5IDggbWludXRlcyBkdXJpbmcgcGVhayBob3VycykuCmBgYHtyfQoKRGVsdFRpbWVfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpICU+JSAKICBtdXRhdGUoUGN0aWxlID0gbnRpbGUoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lLCAxMDApLAogICAgICAgICBNaW5SID0gbWluX3JhbmsoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpLAogICAgICAgICBQY3RSX1JvdW5kID0gcm91bmQoUGN0UiwgMikKICAgICAgICApIAoKY29sbmFtZXMoRGVsdFRpbWVfTnRpbGUpWzFdIDwtICJEZWx0YV9UaW1lIgpzdHIoRGVsdFRpbWVfTnRpbGUpCgpEZWx0VGltZV9OdGlsZV9Sb3dzIDwtIG5yb3coRGVsdFRpbWVfTnRpbGUpCgpWaWV3KHRhaWwoRGVsdFRpbWVfTnRpbGUsIDUwMCkpCgoKRGVsdFRpbWVfUGN0aWxlcyA8LSBncm91cF9ieShEZWx0VGltZV9OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5EZWx0VGltZUF0UGN0aWxlID0gbWluKERlbHRhX1RpbWUpLAogICAgQ250c0F0UGN0aWxlID0gbigpLAogICAgUGN0c0F0UGN0aWxlID0gQ250c0F0UGN0aWxlIC8gRGVsdFRpbWVfTnRpbGVfUm93cwogICkgJT4lIAogIG11dGF0ZShDdW1TdW1QQXRQID0gY3Vtc3VtKFBjdHNBdFBjdGlsZSkKICAgICAgICApCgpWaWV3KERlbHRUaW1lX1BjdGlsZXMpCkRlbHRUaW1lX1BjdGlsZXMKCiMgfjY2JSBvZiByb3dzIGFyZSBiZXR3ZWVuIDUgbWluIGxhdGUgYW5kIDUgbWluIGVhcmx5Cm5yb3coZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgIERlbHRhX1RpbWUgPj0gLTMwMCAmCiAgICAgICAgICAgICAgRGVsdGFfVGltZSA8PSAzMDAKICAgICAgICAgICApCiAgICApIC8gbnJvdyhBbGxEYXlzX05ld09yZGVyKQoKCiMgZXhhbXBsZXMgb2Ygd2VpcmQgbGFyZ2UgRGVsdGFfVGltZXMKVmlldyhmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgRGVsdGFfVGltZSA8IC00MjAyIHwKICAgICAgICAgICAgICBEZWx0YV9UaW1lID4gMTcwNQogICAgICAgICAgICkgJT4lIAogICAgICAgYXJyYW5nZShkZXNjKERlbHRhX1RpbWUpCiAgICAgICAgICAgICAgKQogICAgKQoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEZWx0YV9UaW1lIChob3cgZWFybHkgb3IgbGF0ZSB0aGUgYnVzIGlzKS4KCkRlbHRhX1RpbWUgaGlzdG9ncmFtLgpgYGB7cn0KCkRlbHRUaW1lX0hpc3REZW4gPC0gZ2dwbG90KEFsbERheXNfTmV3T3JkZXIsIGFlcyh4ID0gKERlbHRhX1RpbWUgLyA2MCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gLi5kZW5zaXR5Li4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gKDUvNjApLCBmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAiZGVuc2l0eSIsIGNvbG91ciA9ICJyZWQiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKC01LCA1KSkgKwogIHhsYWIoIkJ1cyBMYXRlbmVzcyAobWluKSIpICsgCiAgeWxhYigiRGVuc2l0eSIpICsgCiAgIyAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKyAKICBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiVmFyaWF0aW9uIGluIEhvdyBFYXJseS9MYXRlIGEgQnVzIElzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBhdG9wKGl0YWxpYygiKHBvc2l0aXZlIHZhbHVlcyBhcmUgbGF0ZSBhcnJpdmFscykiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICkKCkRlbHRUaW1lX0hpc3REZW4KCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRGVsdGFfVGltZSAoaG93IGVhcmx5IG9yIGxhdGUgdGhlIGJ1cyBpcykuCgpEZWx0YV9UaW1lIGJveHBsb3QuCmBgYHtyfQoKIyBDb3VudF9WYWx1ZXMgaXMgbmVlZGVkIHRvIGRpc3BsYXkgdGhlIG1lZGlhbnMgb24gdGhlIGJveCBwbG90cwpDb3VudF9WYWx1ZXMgPC0gZGRwbHkoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgIC4oRXZlbnRfVGltZV9Ickdyb3VwKSwKICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcmlzZSwKICAgICAgICAgICAgICAgICAgICAgIFZhbHVlX0NvdW50cyA9IG1lZGlhbihEZWx0YV9UaW1lIC8gNjAsIG5hLnJtID0gVFJVRSkKICAgICAgICAgICAgICAgICAgICAgKQoKRGVsdFRpbWVfQm94UGxvdCA8LSBnZ3Bsb3QoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKGZhY3RvcihFdmVudF9UaW1lX0hyR3JvdXApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVsdGFfVGltZSAvIDYwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGZhY3RvcihFdmVudF9UaW1lX0hyR3JvdXApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICApICsgCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJyZWQiLCBub3RjaD1UUlVFKSArIAogICMgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC0zMDAsIDEyMDApKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKC01LCAyMCkpICsKICBnZW9tX3RleHQoZGF0YSA9IENvdW50X1ZhbHVlcywKICAgICAgICAgICAgYWVzKHkgPSBWYWx1ZV9Db3VudHMsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGZvcm1hdChyb3VuZChWYWx1ZV9Db3VudHMsIGRpZ2l0cyA9IDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnNtYWxsID0gMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICksCiAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICB2anVzdCA9IC0wLjUKICAgICAgICAgICApICsKICB4bGFiKCJIb3VyIEdyb3VwIikgKyAKICB5bGFiKCJCdXMgTGF0ZW5lc3MgKG1pbnV0ZXMpIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZT00NSkpICsgCiAgI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiLCBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiSG93IEVhcmx5L0xhdGUgaXMgdGhlIEJ1cyAoYnkgSG91ciBHcm91cCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGF0b3AoaXRhbGljKCIocG9zaXRpdmUgdmFsdWVzIGFyZSBsYXRlIGFycml2YWxzKSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgKQoKRGVsdFRpbWVfQm94UGxvdAoKYGBgCgoKSW52ZXN0aWdhdGlvbiBvZiBEZWx0YV9UaW1lIChob3cgZWFybHkgb3IgbGF0ZSB0aGUgYnVzIGlzKS4KCkV4cGxvcmluZyAiZXh0cmVtZSIgRGVsdGFfVGltZXMuICBGaXJzdCBsZXQncyBnZXQgc29tZSAicmFuayIgc3RhdHMuCmBgYHtyfQoKVmlldyhEZWx0VGltZV9QY3RpbGVzKQpEZWx0VGltZV9QY3RpbGVzCgoKRGVsdFRpbWVBYnNfTnRpbGUgPC0gYXMuZGF0YS5mcmFtZShhYnMoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSkgJT4lIAogIG11dGF0ZShQY3RpbGUgPSBudGlsZShhYnMoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSwgMTAwKSwKICAgICAgICAgTWluUiA9IG1pbl9yYW5rKGFicyhBbGxEYXlzX05ld09yZGVyJERlbHRhX1RpbWUpKSwKICAgICAgICAgUGN0UiA9IHBlcmNlbnRfcmFuayhhYnMoQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lKSksCiAgICAgICAgIFBjdFJfUm91bmQgPSByb3VuZChQY3RSLCAyKQogICAgICAgICkgCgpjb2xuYW1lcyhEZWx0VGltZUFic19OdGlsZSlbMV0gPC0gIkRlbHRhX1RpbWVfQWJzIgpzdHIoRGVsdFRpbWVBYnNfTnRpbGUpCgpEZWx0VGltZUFic19OdGlsZV9Sb3dzIDwtIG5yb3coRGVsdFRpbWVBYnNfTnRpbGUpCgpWaWV3KHRhaWwoRGVsdFRpbWVBYnNfTnRpbGUsIDUwMCkpCgoKRGVsdFRpbWVBYnNfUGN0aWxlcyA8LSBncm91cF9ieShEZWx0VGltZUFic19OdGlsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQY3RSX1JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBzdW1tYXJpc2UoCiAgICBNaW5EZWx0VGltZUF0UGN0aWxlID0gbWluKERlbHRhX1RpbWVfQWJzKSwKICAgIENudHNBdFBjdGlsZSA9IG4oKSwKICAgIFBjdHNBdFBjdGlsZSA9IENudHNBdFBjdGlsZSAvIERlbHRUaW1lX050aWxlX1Jvd3MKICApICU+JSAKICBtdXRhdGUoQ3VtU3VtUEF0UCA9IGN1bXN1bShQY3RzQXRQY3RpbGUpCiAgICAgICAgKQoKVmlldyhEZWx0VGltZUFic19QY3RpbGVzKQpEZWx0VGltZUFic19QY3RpbGVzCgpgYGAKCgpJbnZlc3RpZ2F0aW9uIG9mIERlbHRhX1RpbWUgKGhvdyBlYXJseSBvciBsYXRlIHRoZSBidXMgaXMpLgoKRXhwbG9yaW5nICJleHRyZW1lIiBEZWx0YV9UaW1lcy4gIFRoZW4gbGV0J3MgY2FsY3VsYXRlIHRoZSBwZXJjZW50YWdlIG9mIGJ1c2VzIHRoYXQgYXJlIDEwIG1pbnV0ZXMgKG9yIG1vcmUpIGxhdGUvZWFybHkuCmBgYHtyfQoKSHJHcm91cF9EZWx0YVRpbWVfQWxsIDwtIGdyb3VwX2J5KEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFdmVudF9UaW1lX0hyR3JvdXAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAlPiUgCiAgc3VtbWFyaXNlKEV2ZW50QWxsX0NudCA9IG4oKQogICAgICAgICAgICkKCnN0cihIckdyb3VwX0RlbHRhVGltZV9BbGwpClZpZXcoSHJHcm91cF9EZWx0YVRpbWVfQWxsKQoKCkhyR3JvdXBfRGVsdGFUaW1lX0Fib3ZlMTBNaW4gPC0gZmlsdGVyKEFsbERheXNfTmV3T3JkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFicyhEZWx0YV9UaW1lKSA+PSA2MDAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBncm91cF9ieShFdmVudF9UaW1lX0hyR3JvdXApICU+JSAKICBzdW1tYXJpc2UoRXZlbnRBYm92ZTEwX0NudCA9IG4oKQogICAgICAgICAgICkKCnN0cihIckdyb3VwX0RlbHRhVGltZV9BYm92ZTEwTWluKQpWaWV3KEhyR3JvdXBfRGVsdGFUaW1lX0Fib3ZlMTBNaW4pCgoKSHJHcm91cF9EZWx0YVRpbWVDb21wYXJlIDwtIGlubmVyX2pvaW4oSHJHcm91cF9EZWx0YVRpbWVfQWJvdmUxME1pbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSHJHcm91cF9EZWx0YVRpbWVfQWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIkV2ZW50X1RpbWVfSHJHcm91cCIgPSAiRXZlbnRfVGltZV9Ickdyb3VwIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICU+JSAKICBtdXRhdGUoUGN0RXZlbnRzQWJvdmUxMCA9IEV2ZW50QWJvdmUxMF9DbnQgLyBFdmVudEFsbF9DbnQpCgpWaWV3KEhyR3JvdXBfRGVsdGFUaW1lQ29tcGFyZSkKCmBgYAoKCkludmVzdGlnYXRpb24gb2YgRGVsdGFfVGltZSAoaG93IGVhcmx5IG9yIGxhdGUgdGhlIGJ1cyBpcykuCgpRdWlja2x5IHBsb3QgdGhlc2UgImV4dHJlbWUiIERlbHRhX1RpbWVzLiAKYGBge3J9CgpEZWx0VGltZV9BYm92ZTEwX0NvbHMgPC0gZ2dwbG90KEhyR3JvdXBfRGVsdGFUaW1lQ29tcGFyZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoZmFjdG9yKEV2ZW50X1RpbWVfSHJHcm91cCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBjdEV2ZW50c0Fib3ZlMTAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX2NvbChmaWxsID0gImxpZ2h0Ymx1ZSIsIGNvbG91ciA9ICJncmV5NjAiLCBzaXplID0gMC4yKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGZvcm1hdChyb3VuZChQY3RFdmVudHNBYm92ZTEwLCBkaWdpdHMgPSAyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5zbWFsbCA9IDIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICApLAogICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgbnVkZ2VfeSA9IChIckdyb3VwX0RlbHRhVGltZUNvbXBhcmUkUGN0RXZlbnRzQWJvdmUxMCAqIC0wLjEpCiAgICAgICAgICAgKSArCiAgIyBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoLTUsIDUpKSArCiAgeGxhYigiSG91ciBHcm91cCIpICsgCiAgeWxhYigiUGVyY2VudCBvZiBBbGwgQnVzIEFycml2YWxzIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlPTQ1KSkgKwogIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJXaGVuIGlzIGEgQnVzIDEwKyBNaW51dGVzIExhdGUvRWFybHkiCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAsYXRvcChpdGFsaWMoInBvc2l0aXZlIHZhbHVlcyBhcmUgbGF0ZSBhcnJpdmFscyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAiIgogICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICkKCkRlbHRUaW1lX0Fib3ZlMTBfQ29scwoKYGBgCgoKUXVpY2sgaW52ZXN0aWdhdGlvbiBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRHdlbGxfVGltZTIgKHRoZSB0aW1lIGEgYnVzIGlzIGF0IGEgc3RvcCkgYW5kIERlbHRhX1RpbWUgKGhvdyBlYXJseS9sYXRlIHRoZSBidXMgaXMpLgoKQ29ycmVsYXRpb24uCmBgYHtyfQoKRHdlbGxURGVsdGFUX0NvcnIgPC0gYXMubWF0cml4KGNvcih4ID0gQWxsRGF5c19OZXdPcmRlciREd2VsbF9UaW1lMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdPcmRlciREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZSA9ICJwYWlyd2lzZSIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKCkR3ZWxsVERlbHRhVF9Db3JyCgpgYGAKCgpRdWljayBpbnZlc3RpZ2F0aW9uIG9uIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBEd2VsbF9UaW1lMiAodGhlIHRpbWUgYSBidXMgaXMgYXQgYSBzdG9wKSBhbmQgRGVsdGFfVGltZSAoaG93IGVhcmx5L2xhdGUgdGhlIGJ1cyBpcykuCgpOZXh0LCBsZXQncyBnZXQgYSBzYW1wbGUgb2YgZGF0YSBmb3IgcGxvdHRpbmcuIExldCdzIGRvIHRoaXMgZm9yIHRoZSBmdWxsIGRhdGFzZXQgKEFsbERheXNfTmV3T3JkZXIpLgpgYGB7cn0KCkFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wIDwtIHNhbXBsZV9mcmFjKEFsbERheXNfTmV3T3JkZXIsIDAuMSkgJT4lIAogIHNlbGVjdChEZWx0YV9UaW1lLAogICAgICAgICBEd2VsbF9UaW1lMgogICAgICAgICkgJT4lIAogIG11dGF0ZShEYXRhU2V0ID0gIkFsbERhdGEiKQoKc3RyKEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wKQoKYGBgCgoKUXVpY2sgaW52ZXN0aWdhdGlvbiBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gRHdlbGxfVGltZTIgKHRoZSB0aW1lIGEgYnVzIGlzIGF0IGEgc3RvcCkgYW5kIERlbHRhX1RpbWUgKGhvdyBlYXJseS9sYXRlIHRoZSBidXMgaXMpLgoKTGV0J3MgYWxzbyBnZXQgYSBzYW1wbGUgb2YgZGF0YSBmb3IgcGxvdHRpbmcsIGJ1dCB3aXRoIGEgZGF0c2V0IHRoYXQgcmVtb3ZlcyBvdXRsaWVycy4KYGBge3J9CgpWaWV3KERlbHRUaW1lX1BjdGlsZXMpClZpZXcoRHdlbGxUaW1lMl9QY3RpbGVzKQoKQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCA8LSBmaWx0ZXIoQWxsRGF5c19OZXdPcmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV0d2VlbihEZWx0YV9UaW1lLCAtNDAyLCAxNzA1KSAmICMgcmVtb3ZlcyBhYm91dCAyJSBvZiBEZWx0YV9UaW1lIHZhbHVlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJldHdlZW4oRHdlbGxfVGltZTIsIDEsIDYzKSAgIyByZW1vdmVzIGFib3V0IDIlIG9mIER3ZWxsX1RpbWUyIHZhbHVlcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgJT4lIAogIHNhbXBsZV9mcmFjKDAuMSkgJT4lIAogIHNlbGVjdChEZWx0YV9UaW1lLAogICAgICAgICBEd2VsbF9UaW1lMgogICAgICAgICkgJT4lIAogIG11dGF0ZShEYXRhU2V0ID0gIk91dGxpZXJzUmVtb3ZlZCIpCgpzdHIoQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCkKCmBgYAoKClF1aWNrIGludmVzdGlnYXRpb24gb24gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIER3ZWxsX1RpbWUyICh0aGUgdGltZSBhIGJ1cyBpcyBhdCBhIHN0b3ApIGFuZCBEZWx0YV9UaW1lIChob3cgZWFybHkvbGF0ZSB0aGUgYnVzIGlzKS4KClBsb3R0aW5nIHRoZSBkYXRhIGZyb20gdGhlIGRhdGFzZXQgdGhhdCBkb2VzIG5vdCByZW1vdmUgb3V0bGllcnMuCmBgYHtyfQoKRHdlbGxURGVsdGFUX1NjYXR0ZXIgPC0gZ2dwbG90KEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKER3ZWxsX1RpbWUyLCBEZWx0YV9UaW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICApICsKICBnZW9tX3BvaW50KHNoYXBlID0gMSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9zaGFwZShzb2xpZCA9IEZBTFNFKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gInJlZCIpICsKICAjIHhsYWIoIlRpbWUgYXQgU3RvcCAoc2VjKSIpICsgCiAgIyB5bGFiKCJMYXRlbmVzcyAoc2VjKSIpICsKICBhbm5vdGF0ZShsYWJlbCA9IGxtX2VxbihkZiA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBBbGxEYXlzX05ld09yZGVyXzEwUGN0U2FtcCREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBBbGxEYXlzX05ld09yZGVyXzEwUGN0U2FtcCREd2VsbF9UaW1lMgogICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICB4ID0gMjIwMCwKICAgICAgICAgICB5ID0gNjAwLAogICAgICAgICAgIGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgY29sb3VyID0gInJlZCIsCiAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICBsYWJzKHRpdGxlID0gIkxhdGVuZXNzIHZzIFRpbWUgYXQgU3RvcCIsCiAgICAgICBzdWJ0aXRsZSA9ICIobm8gb3V0bGllcnMgcmVtb3ZlZCkiLAogICAgICAgeCA9ICJUaW1lIGF0IFN0b3AgKHNlYykiLAogICAgICAgeSA9ICJMYXRlbmVzcyAoc2VjKSIKICAgICAgKQogICMgZ2d0aXRsZShleHByZXNzaW9uKGF0b3AoIkxhdGVuZXNzIHZzIFRpbWUgYXQgU3RvcCIKICAjICAgICAgICAgICAgICAgICAgICAgICAgICxhdG9wKGl0YWxpYygiKG5vIG91dGxpZXJzIHJlbW92ZWQpIiksCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIgogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICkKICAjICAgICAgICAgICAgICAgICAgICkKICAjICAgICAgICApCiMgKwojICAgZ2VvbV9qaXR0ZXIoKQoKRHdlbGxURGVsdGFUX1NjYXR0ZXIKCmBgYAoKClF1aWNrIGludmVzdGlnYXRpb24gb24gdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIER3ZWxsX1RpbWUyICh0aGUgdGltZSBhIGJ1cyBpcyBhdCBhIHN0b3ApIGFuZCBEZWx0YV9UaW1lIChob3cgZWFybHkvbGF0ZSB0aGUgYnVzIGlzKS4KClBsb3R0aW5nIHRoZSBkYXRhIGZyb20gdGhlIGRhdGFzZXQgdGhhdCBkb2VzIHJlbW92ZSBvdXRsaWVycy4KYGBge3J9CgpEd2VsbFREZWx0YVRfU2NhdHRlcl9Ob0V4dHJlbWVzIDwtIGdncGxvdChBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoRHdlbGxfVGltZTIsIERlbHRhX1RpbWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEsIGFscGhhID0gMC41KSArCiAgc2NhbGVfc2hhcGUoc29saWQgPSBGQUxTRSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9ICJibHVlIikgKwogICMgeGxhYigiVGltZSBhdCBTdG9wIChzZWMpIikgKyAKICAjIHlsYWIoIkxhdGVuZXNzIChzZWMpIikgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wJER3ZWxsX1RpbWUyCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIHggPSA1MCwKICAgICAgICAgICB5ID0gLTQ3NSwKICAgICAgICAgICBnZW9tID0gInRleHQiLAogICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgIGNvbG91ciA9ICJibHVlIiwKICAgICAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgICAgICkgKwogIGxhYnModGl0bGUgPSAiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIiwKICAgICAgIHN1YnRpdGxlID0gIigyJSBvZiBvdXRsaWVycyByZW1vdmVkKSIsCiAgICAgICB4ID0gIlRpbWUgYXQgU3RvcCAoc2VjKSIsCiAgICAgICB5ID0gIkxhdGVuZXNzIChzZWMpIgogICAgICApCiAgIyBnZ3RpdGxlKGV4cHJlc3Npb24oYXRvcCgiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIgogICMgICAgICAgICAgICAgICAgICAgICAgICAgLGF0b3AoaXRhbGljKCIoMiUgb2Ygb3V0bGllcnMgcmVtb3ZlZCkiKSwKICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAjICAgICAgICAgICAgICAgICAgICAgICAgKQogICMgICAgICAgICAgICAgICAgICAgKQogICMgICAgICAgICkKIyArCiMgICBnZW9tX2ppdHRlcigpCgpEd2VsbFREZWx0YVRfU2NhdHRlcl9Ob0V4dHJlbWVzCgpgYGAKCgpRdWljayBpbnZlc3RpZ2F0aW9uIG9uIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBEd2VsbF9UaW1lMiAodGhlIHRpbWUgYSBidXMgaXMgYXQgYSBzdG9wKSBhbmQgRGVsdGFfVGltZSAoaG93IGVhcmx5L2xhdGUgdGhlIGJ1cyBpcykuCgpQbG90dGluZyB0aGUgZGF0YSBmcm9tIGJvdGggZGF0YXNldHMgdG9nZXRoZXIuCmBgYHtyfQoKQ29tYmluZWREYXRhIDwtIHJiaW5kKEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wLAogICAgICAgICAgICAgICAgICAgICAgQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcAogICAgICAgICAgICAgICAgICAgICApCgpDb21iaW5lZERhdGEkRGF0YVNldCA8LSBmYWN0b3IoQ29tYmluZWREYXRhJERhdGFTZXQpCgpzdHIoQ29tYmluZWREYXRhKQoKCkR3ZWxsVERlbHRhVF9TY2F0dGVyX0NvbWJpbmVkIDwtIGdncGxvdChDb21iaW5lZERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IER3ZWxsX1RpbWUyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBEZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IERhdGFTZXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDEsIGFscGhhID0gMC41KSArCiAgc2NhbGVfc2hhcGUoc29saWQgPSBGQUxTRSkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCA1MDApLCB5bGltID0gYygtMTAwMCwgMjAwMCkKICAgICAgICAgICAgICAgICApICsKICBnZW9tX3Ntb290aChkYXRhID0gZmlsdGVyKENvbWJpbmVkRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIERhdGFTZXQgPT0gIkFsbERhdGEiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwKICAgICAgICAgICAgICBjb2xvdXIgPSAicmVkIgogICAgICAgICAgICAgKSArCiAgZ2VvbV9zbW9vdGgoZGF0YSA9IGZpbHRlcihDb21iaW5lZERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRhU2V0ID09ICJPdXRsaWVyc1JlbW92ZWQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwKICAgICAgICAgICAgICBjb2xvdXIgPSAiYmx1ZSIKICAgICAgICAgICAgICkgKwogICMgZmFjZXRfd3JhcCggfiBEYXRhU2V0LCBuY29sID0gMikgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdPcmRlcl8xMFBjdFNhbXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wJERlbHRhX1RpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IEFsbERheXNfTmV3T3JkZXJfMTBQY3RTYW1wJER3ZWxsX1RpbWUyCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIHggPSAzMDAsCiAgICAgICAgICAgeSA9IC02MDAsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAicmVkIiwKICAgICAgICAgICBwYXJzZSA9IFRSVUUKICAgICAgICAgICkgKwogIGFubm90YXRlKGxhYmVsID0gbG1fZXFuKGRmID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQWxsRGF5c19OZXdPcmRlcl9Ob0V4dHJlbWVzXzEwUGN0U2FtcCREZWx0YV9UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBBbGxEYXlzX05ld09yZGVyX05vRXh0cmVtZXNfMTBQY3RTYW1wJER3ZWxsX1RpbWUyCiAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgIHggPSAzMDAsCiAgICAgICAgICAgeSA9IC04MDAsCiAgICAgICAgICAgZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICBjb2xvdXIgPSAiYmx1ZSIsCiAgICAgICAgICAgcGFyc2UgPSBUUlVFCiAgICAgICAgICApICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIGxhYnModGl0bGUgPSAiTGF0ZW5lc3MgdnMgVGltZSBhdCBTdG9wIiwKICAgICAgIHggPSAiVGltZSBhdCBTdG9wIChzZWMpIiwKICAgICAgIHkgPSAiTGF0ZW5lc3MgKHNlYykiCiAgICAgICkKICAjIGdndGl0bGUoZXhwcmVzc2lvbihhdG9wKCJMYXRlbmVzcyB2cyBUaW1lIGF0IFN0b3AiCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAsYXRvcChpdGFsaWMoIjIlIG9mIG91dGxpZXJzIHJlbW92ZWQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgICIiCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICkKICAgICAgICAgIyAgICAgICAgICAgICAgICAgKQogICAgICAgICAjICAgICAgICAgICAgKQogICAgICAgICAjICkKIyArCiMgICBnZW9tX2ppdHRlcigpCgpEd2VsbFREZWx0YVRfU2NhdHRlcl9Db21iaW5lZAoKYGBgCgoKCgoKCgoKCgoKQWRkIGEgbmV3IGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqSW5zZXJ0IENodW5rKiBidXR0b24gb24gdGhlIHRvb2xiYXIgb3IgYnkgcHJlc3NpbmcgKkNtZCtPcHRpb24rSSouCgpXaGVuIHlvdSBzYXZlIHRoZSBub3RlYm9vaywgYW4gSFRNTCBmaWxlIGNvbnRhaW5pbmcgdGhlIGNvZGUgYW5kIG91dHB1dCB3aWxsIGJlIHNhdmVkIGFsb25nc2lkZSBpdCAoY2xpY2sgdGhlICpQcmV2aWV3KiBidXR0b24gb3IgcHJlc3MgKkNtZCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgo=